1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2013 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/>. */
27 #include <readline/readline.h>
28 #include <readline/history.h>
31 static char *history_file;
33 static char **complete_command_name (const char *, int, int);
34 static char **dont_complete (const char *, int, int);
35 static char *command_generator (const char *text, int state);
39 #include "ui/terminal/terminal-reader.h"
40 #include <sys/select.h>
42 #include <sys/types.h>
49 #include "data/settings.h"
50 #include "language/command.h"
51 #include "language/lexer/lexer.h"
52 #include "libpspp/assertion.h"
53 #include "libpspp/cast.h"
54 #include "libpspp/message.h"
55 #include "libpspp/prompt.h"
56 #include "libpspp/str.h"
57 #include "libpspp/version.h"
58 #include "output/driver.h"
59 #include "output/journal.h"
60 #include "ui/terminal/terminal.h"
62 #include "gl/minmax.h"
63 #include "gl/xalloc.h"
66 #define _(msgid) gettext (msgid)
68 struct terminal_reader
70 struct lex_reader reader;
76 static int n_terminal_readers;
78 static void readline_init (void);
79 static void readline_done (void);
80 static bool readline_read (struct substring *, enum prompt_style);
82 /* Display a welcoming message. */
86 static bool welcomed = false;
90 fputs ("PSPP is free software and you are welcome to distribute copies of "
91 "it\nunder certain conditions; type \"show copying.\" to see the "
92 "conditions.\nThere is ABSOLUTELY NO WARRANTY for PSPP; type \"show "
93 "warranty.\" for details.\n", stdout);
94 puts (announced_version);
98 static struct terminal_reader *
99 terminal_reader_cast (struct lex_reader *r)
101 return UP_CAST (r, struct terminal_reader, reader);
105 /* Older libreadline versions do not provide rl_outstream.
106 However, it is almost always going to be the same as stdout. */
107 #if ! HAVE_RL_OUTSTREAM
108 # define rl_outstream stdout
113 /* Similarly, rl_echo_signal_char is fairly recent.
114 We provide our own crude version if it is not present. */
115 #if ! HAVE_RL_ECHO_SIGNAL_CHAR
117 rl_echo_signal_char (int sig)
121 if (0 == tcgetattr (0, &t))
123 cc_t c = t.c_cc[VINTR];
125 if (c >= 0 && c <= 'Z' - 'A')
126 fprintf (rl_outstream, "^%c", 'A' + c - 1);
128 fprintf (rl_outstream, "%c", c);
132 fprintf (rl_outstream, "^C");
134 fflush (rl_outstream);
141 terminal_reader_read (struct lex_reader *r_, char *buf, size_t n,
142 enum prompt_style prompt_style)
144 struct terminal_reader *r = terminal_reader_cast (r_);
147 if (r->offset >= r->s.length && !r->eof)
150 msg_ui_reset_counts ();
154 if (! readline_read (&r->s, prompt_style))
157 fprintf (rl_outstream, "\n");
161 r->eof = ss_is_empty (r->s);
163 /* Check whether the size of the window has changed, so that
164 the output drivers can adjust their settings as needed. We
165 only do this for the first line of a command, as it's
166 possible that the output drivers are actually in use
167 afterward, and we don't want to confuse them in the middle
169 if (prompt_style == PROMPT_FIRST)
170 terminal_check_size ();
173 chunk = MIN (n, r->s.length - r->offset);
174 memcpy (buf, r->s.string + r->offset, chunk);
180 terminal_reader_close (struct lex_reader *r_)
182 struct terminal_reader *r = terminal_reader_cast (r_);
185 free (r->reader.file_name);
188 if (!--n_terminal_readers)
192 static struct lex_reader_class terminal_reader_class =
194 terminal_reader_read,
195 terminal_reader_close
198 /* Creates a source which uses readln to get its line */
200 terminal_reader_create (void)
202 struct terminal_reader *r;
204 if (!n_terminal_readers++)
207 r = xzalloc (sizeof *r);
208 r->reader.class = &terminal_reader_class;
209 r->reader.syntax = LEX_SYNTAX_INTERACTIVE;
210 r->reader.error = LEX_ERROR_TERMINAL;
211 r->reader.file_name = NULL;
221 readline_prompt (enum prompt_style style)
237 case PROMPT_DOCUMENT:
240 case PROMPT_DO_REPEAT:
241 return "DO REPEAT> ";
251 static bool sigint_received ;
254 A function similar to getc from stdio.
255 However this one may be interrupted by SIGINT.
256 If that happens it will return EOF and the global variable
257 sigint_received will be set to true.
260 interruptible_getc (FILE *fp)
266 struct timeval timeout = {0, 50000};
272 max_fd = (max_fd > fd) ? max_fd : fd;
275 max_fd = (max_fd > fd) ? max_fd : fd;
277 ret = select (max_fd + 1, &what, NULL, NULL, &timeout);
278 if ( ret == -1 && errno != EINTR)
280 perror ("Select failed");
286 if (FD_ISSET (pfd[0], &what))
289 read (pfd[0], dummy, 1);
290 sigint_received = true;
297 /* This will not block! */
298 read (fileno (fp), &c, 1);
308 write (pfd[1], "x", 1);
309 rl_echo_signal_char (sig);
316 if ( 0 != pipe2 (pfd, O_NONBLOCK))
317 perror ("Cannot create pipe");
319 if ( SIG_ERR == signal (SIGINT, handler))
320 perror ("Cannot add signal handler");
322 rl_catch_signals = 0;
323 rl_getc_function = interruptible_getc;
324 rl_basic_word_break_characters = "\n";
326 stifle_history (500);
327 if (history_file == NULL)
329 const char *home_dir = getenv ("HOME");
330 if (home_dir != NULL)
332 history_file = xasprintf ("%s/.pspp_history", home_dir);
333 read_history (history_file);
341 if (history_file != NULL && false == settings_get_testing_mode () )
342 write_history (history_file);
347 /* Prompt the user for a line of input and return it in LINE.
348 Returns true if the LINE should be considered valid, false otherwise.
351 readline_read (struct substring *line, enum prompt_style style)
355 rl_attempted_completion_function = (style == PROMPT_FIRST
356 ? complete_command_name
358 sigint_received = false;
359 string = readline (readline_prompt (style));
371 add_history (string);
373 end = strchr (string, '\0');
375 *line = ss_buffer (string, end - string + 1);
383 /* Returns a set of command name completions for TEXT.
384 This is of the proper form for assigning to
385 rl_attempted_completion_function. */
387 complete_command_name (const char *text, int start, int end UNUSED)
391 /* Complete command name at start of line. */
392 return rl_completion_matches (text, command_generator);
396 /* Otherwise don't do any completion. */
397 rl_attempted_completion_over = 1;
402 /* Do not do any completion for TEXT. */
404 dont_complete (const char *text UNUSED, int start UNUSED, int end UNUSED)
406 rl_attempted_completion_over = 1;
410 /* If STATE is 0, returns the first command name matching TEXT.
411 Otherwise, returns the next command name matching TEXT.
412 Returns a null pointer when no matches are left. */
414 command_generator (const char *text, int state)
416 static const struct command *cmd;
421 name = cmd_complete (text, &cmd);
422 return name ? xstrdup (name) : NULL;
425 #else /* !HAVE_READLINE */
438 readline_read (struct substring *line, enum prompt_style style)
440 struct string string;
441 const char *prompt = readline_prompt (style);
443 fputs (prompt, stdout);
445 ds_init_empty (&string);
446 ds_read_line (&string, stdin, SIZE_MAX);
452 #endif /* !HAVE_READLINE */