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>
48 #include "data/settings.h"
49 #include "language/command.h"
50 #include "language/lexer/lexer.h"
51 #include "libpspp/assertion.h"
52 #include "libpspp/cast.h"
53 #include "libpspp/message.h"
54 #include "libpspp/prompt.h"
55 #include "libpspp/str.h"
56 #include "libpspp/version.h"
57 #include "output/driver.h"
58 #include "output/journal.h"
59 #include "ui/terminal/terminal.h"
61 #include "gl/minmax.h"
62 #include "gl/xalloc.h"
65 #define _(msgid) gettext (msgid)
67 struct terminal_reader
69 struct lex_reader reader;
75 static int n_terminal_readers;
77 static void readline_init (void);
78 static void readline_done (void);
79 static bool readline_read (struct substring *, enum prompt_style);
81 /* Display a welcoming message. */
85 static bool welcomed = false;
89 fputs ("PSPP is free software and you are welcome to distribute copies of "
90 "it\nunder certain conditions; type \"show copying.\" to see the "
91 "conditions.\nThere is ABSOLUTELY NO WARRANTY for PSPP; type \"show "
92 "warranty.\" for details.\n", stdout);
93 puts (announced_version);
97 static struct terminal_reader *
98 terminal_reader_cast (struct lex_reader *r)
100 return UP_CAST (r, struct terminal_reader, reader);
104 /* Older libreadline versions do not provide rl_outstream.
105 However, it is almost always going to be the same as stdout. */
106 #if ! HAVE_RL_OUTSTREAM
107 # define rl_outstream stdout
112 /* Similarly, rl_echo_signal_char is fairly recent.
113 We provide our own crude version if it is not present. */
114 #if ! HAVE_RL_ECHO_SIGNAL_CHAR
116 rl_echo_signal_char (int sig)
120 if (0 == tcgetattr (0, &t))
122 cc_t c = t.c_cc[VINTR];
124 if (c >= 0 && c <= 'Z' - 'A')
125 fprintf (rl_outstream, "^%c", 'A' + c - 1);
127 fprintf (rl_outstream, "%c", c);
131 fprintf (rl_outstream, "^C");
133 fflush (rl_outstream);
140 terminal_reader_read (struct lex_reader *r_, char *buf, size_t n,
141 enum prompt_style prompt_style)
143 struct terminal_reader *r = terminal_reader_cast (r_);
146 if (r->offset >= r->s.length && !r->eof)
149 msg_ui_reset_counts ();
153 if (! readline_read (&r->s, prompt_style))
156 fprintf (rl_outstream, "\n");
160 r->eof = ss_is_empty (r->s);
162 /* Check whether the size of the window has changed, so that
163 the output drivers can adjust their settings as needed. We
164 only do this for the first line of a command, as it's
165 possible that the output drivers are actually in use
166 afterward, and we don't want to confuse them in the middle
168 if (prompt_style == PROMPT_FIRST)
169 terminal_check_size ();
172 chunk = MIN (n, r->s.length - r->offset);
173 memcpy (buf, r->s.string + r->offset, chunk);
179 terminal_reader_close (struct lex_reader *r_)
181 struct terminal_reader *r = terminal_reader_cast (r_);
184 free (r->reader.file_name);
187 if (!--n_terminal_readers)
191 static struct lex_reader_class terminal_reader_class =
193 terminal_reader_read,
194 terminal_reader_close
197 /* Creates a source which uses readln to get its line */
199 terminal_reader_create (void)
201 struct terminal_reader *r;
203 if (!n_terminal_readers++)
206 r = xzalloc (sizeof *r);
207 r->reader.class = &terminal_reader_class;
208 r->reader.syntax = LEX_SYNTAX_INTERACTIVE;
209 r->reader.error = LEX_ERROR_TERMINAL;
210 r->reader.file_name = NULL;
220 readline_prompt (enum prompt_style style)
236 case PROMPT_DOCUMENT:
239 case PROMPT_DO_REPEAT:
240 return "DO REPEAT> ";
250 static bool sigint_received ;
253 A function similar to getc from stdio.
254 However this one may be interrupted by SIGINT.
255 If that happens it will return EOF and the global variable
256 sigint_received will be set to true.
259 interruptible_getc (FILE *fp)
265 struct timeval timeout = {0, 50000};
271 max_fd = (max_fd > fd) ? max_fd : fd;
274 max_fd = (max_fd > fd) ? max_fd : fd;
276 ret = select (max_fd + 1, &what, NULL, NULL, &timeout);
277 if ( ret == -1 && errno != EINTR)
279 perror ("Select failed");
285 if (FD_ISSET (pfd[0], &what))
288 read (pfd[0], dummy, 1);
289 sigint_received = true;
296 /* This will not block! */
297 read (fileno (fp), &c, 1);
307 write (pfd[1], "x", 1);
308 rl_echo_signal_char (sig);
315 if ( 0 != pipe2 (pfd, O_NONBLOCK))
316 perror ("Cannot create pipe");
318 if ( SIG_ERR == signal (SIGINT, handler))
319 perror ("Cannot add signal handler");
321 rl_catch_signals = 0;
322 rl_getc_function = interruptible_getc;
323 rl_basic_word_break_characters = "\n";
325 stifle_history (500);
326 if (history_file == NULL)
328 const char *home_dir = getenv ("HOME");
329 if (home_dir != NULL)
331 history_file = xasprintf ("%s/.pspp_history", home_dir);
332 read_history (history_file);
340 if (history_file != NULL && false == settings_get_testing_mode () )
341 write_history (history_file);
346 /* Prompt the user for a line of input and return it in LINE.
347 Returns true if the LINE should be considered valid, false otherwise.
350 readline_read (struct substring *line, enum prompt_style style)
354 rl_attempted_completion_function = (style == PROMPT_FIRST
355 ? complete_command_name
357 sigint_received = false;
358 string = readline (readline_prompt (style));
370 add_history (string);
372 end = strchr (string, '\0');
374 *line = ss_buffer (string, end - string + 1);
382 /* Returns a set of command name completions for TEXT.
383 This is of the proper form for assigning to
384 rl_attempted_completion_function. */
386 complete_command_name (const char *text, int start, int end UNUSED)
390 /* Complete command name at start of line. */
391 return rl_completion_matches (text, command_generator);
395 /* Otherwise don't do any completion. */
396 rl_attempted_completion_over = 1;
401 /* Do not do any completion for TEXT. */
403 dont_complete (const char *text UNUSED, int start UNUSED, int end UNUSED)
405 rl_attempted_completion_over = 1;
409 /* If STATE is 0, returns the first command name matching TEXT.
410 Otherwise, returns the next command name matching TEXT.
411 Returns a null pointer when no matches are left. */
413 command_generator (const char *text, int state)
415 static const struct command *cmd;
420 name = cmd_complete (text, &cmd);
421 return name ? xstrdup (name) : NULL;
424 #else /* !HAVE_READLINE */
437 readline_read (struct substring *line, enum prompt_style style)
439 struct string string;
440 const char *prompt = readline_prompt (style);
442 fputs (prompt, stdout);
444 ds_init_empty (&string);
445 ds_read_line (&string, stdin, SIZE_MAX);
451 #endif /* !HAVE_READLINE */