1*baff8195SBaptiste Daroussin /* $NetBSD: readline.c,v 1.178 2022/12/02 19:23:15 christos Exp $ */
2d0ef721eSBaptiste Daroussin
3d0ef721eSBaptiste Daroussin /*-
4d0ef721eSBaptiste Daroussin * Copyright (c) 1997 The NetBSD Foundation, Inc.
5d0ef721eSBaptiste Daroussin * All rights reserved.
6d0ef721eSBaptiste Daroussin *
7d0ef721eSBaptiste Daroussin * This code is derived from software contributed to The NetBSD Foundation
8d0ef721eSBaptiste Daroussin * by Jaromir Dolecek.
9d0ef721eSBaptiste Daroussin *
10d0ef721eSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without
11d0ef721eSBaptiste Daroussin * modification, are permitted provided that the following conditions
12d0ef721eSBaptiste Daroussin * are met:
13d0ef721eSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright
14d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer.
15d0ef721eSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright
16d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the
17d0ef721eSBaptiste Daroussin * documentation and/or other materials provided with the distribution.
18d0ef721eSBaptiste Daroussin *
19d0ef721eSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20d0ef721eSBaptiste Daroussin * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21d0ef721eSBaptiste Daroussin * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22d0ef721eSBaptiste Daroussin * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23d0ef721eSBaptiste Daroussin * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24d0ef721eSBaptiste Daroussin * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25d0ef721eSBaptiste Daroussin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26d0ef721eSBaptiste Daroussin * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27d0ef721eSBaptiste Daroussin * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28d0ef721eSBaptiste Daroussin * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29d0ef721eSBaptiste Daroussin * POSSIBILITY OF SUCH DAMAGE.
30d0ef721eSBaptiste Daroussin */
31d0ef721eSBaptiste Daroussin
32d0ef721eSBaptiste Daroussin #include "config.h"
33d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID)
34*baff8195SBaptiste Daroussin __RCSID("$NetBSD: readline.c,v 1.178 2022/12/02 19:23:15 christos Exp $");
35d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */
36d0ef721eSBaptiste Daroussin
37d0ef721eSBaptiste Daroussin #include <sys/types.h>
38d0ef721eSBaptiste Daroussin #include <sys/stat.h>
39d0ef721eSBaptiste Daroussin #include <ctype.h>
40d0ef721eSBaptiste Daroussin #include <dirent.h>
41d0ef721eSBaptiste Daroussin #include <errno.h>
42d0ef721eSBaptiste Daroussin #include <fcntl.h>
43d0ef721eSBaptiste Daroussin #include <limits.h>
44d0ef721eSBaptiste Daroussin #include <pwd.h>
45d0ef721eSBaptiste Daroussin #include <setjmp.h>
467f399375SBaptiste Daroussin #include <stdarg.h>
47d0ef721eSBaptiste Daroussin #include <stdint.h>
48d0ef721eSBaptiste Daroussin #include <stdio.h>
49d0ef721eSBaptiste Daroussin #include <stdlib.h>
50d0ef721eSBaptiste Daroussin #include <string.h>
51d0ef721eSBaptiste Daroussin #include <unistd.h>
52d0ef721eSBaptiste Daroussin #include <vis.h>
53d0ef721eSBaptiste Daroussin
54d0ef721eSBaptiste Daroussin #include "readline/readline.h"
55d0ef721eSBaptiste Daroussin #include "el.h"
56d0ef721eSBaptiste Daroussin #include "fcns.h"
57d0ef721eSBaptiste Daroussin #include "filecomplete.h"
58d0ef721eSBaptiste Daroussin
59d0ef721eSBaptiste Daroussin void rl_prep_terminal(int);
60d0ef721eSBaptiste Daroussin void rl_deprep_terminal(void);
61d0ef721eSBaptiste Daroussin
62d0ef721eSBaptiste Daroussin /* for rl_complete() */
63d0ef721eSBaptiste Daroussin #define TAB '\r'
64d0ef721eSBaptiste Daroussin
65d0ef721eSBaptiste Daroussin /* see comment at the #ifdef for sense of this */
66d0ef721eSBaptiste Daroussin /* #define GDB_411_HACK */
67d0ef721eSBaptiste Daroussin
68d0ef721eSBaptiste Daroussin /* readline compatibility stuff - look at readline sources/documentation */
69d0ef721eSBaptiste Daroussin /* to see what these variables mean */
70d0ef721eSBaptiste Daroussin const char *rl_library_version = "EditLine wrapper";
71d0ef721eSBaptiste Daroussin int rl_readline_version = RL_READLINE_VERSION;
72d0ef721eSBaptiste Daroussin static char empty[] = { '\0' };
73d0ef721eSBaptiste Daroussin static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
74d0ef721eSBaptiste Daroussin static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
75d0ef721eSBaptiste Daroussin '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
76d0ef721eSBaptiste Daroussin const char *rl_readline_name = empty;
77d0ef721eSBaptiste Daroussin FILE *rl_instream = NULL;
78d0ef721eSBaptiste Daroussin FILE *rl_outstream = NULL;
79d0ef721eSBaptiste Daroussin int rl_point = 0;
80d0ef721eSBaptiste Daroussin int rl_end = 0;
81d0ef721eSBaptiste Daroussin char *rl_line_buffer = NULL;
82d0ef721eSBaptiste Daroussin rl_vcpfunc_t *rl_linefunc = NULL;
83d0ef721eSBaptiste Daroussin int rl_done = 0;
84d0ef721eSBaptiste Daroussin rl_hook_func_t *rl_event_hook = NULL;
85d0ef721eSBaptiste Daroussin KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
86d0ef721eSBaptiste Daroussin emacs_meta_keymap,
87d0ef721eSBaptiste Daroussin emacs_ctlx_keymap;
88d0ef721eSBaptiste Daroussin /*
89d0ef721eSBaptiste Daroussin * The following is not implemented; we always catch signals in the
90d0ef721eSBaptiste Daroussin * libedit fashion: set handlers on entry to el_gets() and clear them
91d0ef721eSBaptiste Daroussin * on the way out. This simplistic approach works for most cases; if
92d0ef721eSBaptiste Daroussin * it does not work for your application, please let us know.
93d0ef721eSBaptiste Daroussin */
94d0ef721eSBaptiste Daroussin int rl_catch_signals = 1;
95d0ef721eSBaptiste Daroussin int rl_catch_sigwinch = 1;
96d0ef721eSBaptiste Daroussin
97d0ef721eSBaptiste Daroussin int history_base = 1; /* probably never subject to change */
98d0ef721eSBaptiste Daroussin int history_length = 0;
99d0ef721eSBaptiste Daroussin int history_offset = 0;
100d0ef721eSBaptiste Daroussin int max_input_history = 0;
101d0ef721eSBaptiste Daroussin char history_expansion_char = '!';
102d0ef721eSBaptiste Daroussin char history_subst_char = '^';
103d0ef721eSBaptiste Daroussin char *history_no_expand_chars = expand_chars;
104d0ef721eSBaptiste Daroussin Function *history_inhibit_expansion_function = NULL;
105d0ef721eSBaptiste Daroussin char *history_arg_extract(int start, int end, const char *str);
106d0ef721eSBaptiste Daroussin
107d0ef721eSBaptiste Daroussin int rl_inhibit_completion = 0;
108d0ef721eSBaptiste Daroussin int rl_attempted_completion_over = 0;
109d0ef721eSBaptiste Daroussin const char *rl_basic_word_break_characters = break_chars;
110d0ef721eSBaptiste Daroussin char *rl_completer_word_break_characters = NULL;
111d0ef721eSBaptiste Daroussin const char *rl_completer_quote_characters = NULL;
11291f76417SBaptiste Daroussin const char *rl_basic_quote_characters = "\"'";
113d0ef721eSBaptiste Daroussin rl_compentry_func_t *rl_completion_entry_function = NULL;
114d0ef721eSBaptiste Daroussin char *(*rl_completion_word_break_hook)(void) = NULL;
115d0ef721eSBaptiste Daroussin rl_completion_func_t *rl_attempted_completion_function = NULL;
1167f399375SBaptiste Daroussin rl_hook_func_t *rl_pre_input_hook = NULL;
1177f399375SBaptiste Daroussin rl_hook_func_t *rl_startup1_hook = NULL;
118d0ef721eSBaptiste Daroussin int (*rl_getc_function)(FILE *) = NULL;
119d0ef721eSBaptiste Daroussin char *rl_terminal_name = NULL;
120d0ef721eSBaptiste Daroussin int rl_already_prompted = 0;
121d0ef721eSBaptiste Daroussin int rl_filename_completion_desired = 0;
122d0ef721eSBaptiste Daroussin int rl_ignore_completion_duplicates = 0;
123d0ef721eSBaptiste Daroussin int readline_echoing_p = 1;
124d0ef721eSBaptiste Daroussin int _rl_print_completions_horizontally = 0;
125d0ef721eSBaptiste Daroussin VFunction *rl_redisplay_function = NULL;
1267f399375SBaptiste Daroussin rl_hook_func_t *rl_startup_hook = NULL;
127d0ef721eSBaptiste Daroussin VFunction *rl_completion_display_matches_hook = NULL;
128d0ef721eSBaptiste Daroussin VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
129d0ef721eSBaptiste Daroussin VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
130d0ef721eSBaptiste Daroussin KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
1317f399375SBaptiste Daroussin unsigned long rl_readline_state = RL_STATE_NONE;
13291f76417SBaptiste Daroussin int _rl_complete_mark_directories;
13391f76417SBaptiste Daroussin rl_icppfunc_t *rl_directory_completion_hook;
13491f76417SBaptiste Daroussin int rl_completion_suppress_append;
13591f76417SBaptiste Daroussin int rl_sort_completion_matches;
13691f76417SBaptiste Daroussin int _rl_completion_prefix_display_length;
13791f76417SBaptiste Daroussin int _rl_echoing_p;
13891f76417SBaptiste Daroussin int history_max_entries;
13991f76417SBaptiste Daroussin char *rl_display_prompt;
1407f399375SBaptiste Daroussin int rl_erase_empty_line;
141d0ef721eSBaptiste Daroussin
142d0ef721eSBaptiste Daroussin /*
143d0ef721eSBaptiste Daroussin * The current prompt string.
144d0ef721eSBaptiste Daroussin */
145d0ef721eSBaptiste Daroussin char *rl_prompt = NULL;
1467f399375SBaptiste Daroussin char *rl_prompt_saved = NULL;
147d0ef721eSBaptiste Daroussin /*
148d0ef721eSBaptiste Daroussin * This is set to character indicating type of completion being done by
149d0ef721eSBaptiste Daroussin * rl_complete_internal(); this is available for application completion
150d0ef721eSBaptiste Daroussin * functions.
151d0ef721eSBaptiste Daroussin */
152d0ef721eSBaptiste Daroussin int rl_completion_type = 0;
153d0ef721eSBaptiste Daroussin
154d0ef721eSBaptiste Daroussin /*
155d0ef721eSBaptiste Daroussin * If more than this number of items results from query for possible
156d0ef721eSBaptiste Daroussin * completions, we ask user if they are sure to really display the list.
157d0ef721eSBaptiste Daroussin */
158d0ef721eSBaptiste Daroussin int rl_completion_query_items = 100;
159d0ef721eSBaptiste Daroussin
160d0ef721eSBaptiste Daroussin /*
161d0ef721eSBaptiste Daroussin * List of characters which are word break characters, but should be left
162d0ef721eSBaptiste Daroussin * in the parsed text when it is passed to the completion function.
163d0ef721eSBaptiste Daroussin * Shell uses this to help determine what kind of completing to do.
164d0ef721eSBaptiste Daroussin */
165d0ef721eSBaptiste Daroussin const char *rl_special_prefixes = NULL;
166d0ef721eSBaptiste Daroussin
167d0ef721eSBaptiste Daroussin /*
168d0ef721eSBaptiste Daroussin * This is the character appended to the completed words if at the end of
169d0ef721eSBaptiste Daroussin * the line. Default is ' ' (a space).
170d0ef721eSBaptiste Daroussin */
171d0ef721eSBaptiste Daroussin int rl_completion_append_character = ' ';
172d0ef721eSBaptiste Daroussin
173d0ef721eSBaptiste Daroussin /* stuff below is used internally by libedit for readline emulation */
174d0ef721eSBaptiste Daroussin
175d0ef721eSBaptiste Daroussin static History *h = NULL;
176d0ef721eSBaptiste Daroussin static EditLine *e = NULL;
177d0ef721eSBaptiste Daroussin static rl_command_func_t *map[256];
178d0ef721eSBaptiste Daroussin static jmp_buf topbuf;
179d0ef721eSBaptiste Daroussin
180d0ef721eSBaptiste Daroussin /* internal functions */
181d0ef721eSBaptiste Daroussin static unsigned char _el_rl_complete(EditLine *, int);
182d0ef721eSBaptiste Daroussin static unsigned char _el_rl_tstp(EditLine *, int);
183d0ef721eSBaptiste Daroussin static char *_get_prompt(EditLine *);
184d0ef721eSBaptiste Daroussin static int _getc_function(EditLine *, wchar_t *);
185d0ef721eSBaptiste Daroussin static int _history_expand_command(const char *, size_t, size_t,
186d0ef721eSBaptiste Daroussin char **);
187d0ef721eSBaptiste Daroussin static char *_rl_compat_sub(const char *, const char *,
188d0ef721eSBaptiste Daroussin const char *, int);
189d0ef721eSBaptiste Daroussin static int _rl_event_read_char(EditLine *, wchar_t *);
190d0ef721eSBaptiste Daroussin static void _rl_update_pos(void);
191d0ef721eSBaptiste Daroussin
192d0ef721eSBaptiste Daroussin static HIST_ENTRY rl_he;
193d0ef721eSBaptiste Daroussin
194d0ef721eSBaptiste Daroussin /* ARGSUSED */
195d0ef721eSBaptiste Daroussin static char *
_get_prompt(EditLine * el)196d0ef721eSBaptiste Daroussin _get_prompt(EditLine *el __attribute__((__unused__)))
197d0ef721eSBaptiste Daroussin {
198d0ef721eSBaptiste Daroussin rl_already_prompted = 1;
199d0ef721eSBaptiste Daroussin return rl_prompt;
200d0ef721eSBaptiste Daroussin }
201d0ef721eSBaptiste Daroussin
202d0ef721eSBaptiste Daroussin
203d0ef721eSBaptiste Daroussin /*
204d0ef721eSBaptiste Daroussin * read one key from user defined input function
205d0ef721eSBaptiste Daroussin */
206d0ef721eSBaptiste Daroussin static int
207d0ef721eSBaptiste Daroussin /*ARGSUSED*/
_getc_function(EditLine * el,wchar_t * c)208d0ef721eSBaptiste Daroussin _getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c)
209d0ef721eSBaptiste Daroussin {
210d0ef721eSBaptiste Daroussin int i;
211d0ef721eSBaptiste Daroussin
212d0ef721eSBaptiste Daroussin i = (*rl_getc_function)(rl_instream);
213d0ef721eSBaptiste Daroussin if (i == -1)
214d0ef721eSBaptiste Daroussin return 0;
215d0ef721eSBaptiste Daroussin *c = (wchar_t)i;
216d0ef721eSBaptiste Daroussin return 1;
217d0ef721eSBaptiste Daroussin }
218d0ef721eSBaptiste Daroussin
219d0ef721eSBaptiste Daroussin static void
_resize_fun(EditLine * el,void * a)220d0ef721eSBaptiste Daroussin _resize_fun(EditLine *el, void *a)
221d0ef721eSBaptiste Daroussin {
222d0ef721eSBaptiste Daroussin const LineInfo *li;
22391f76417SBaptiste Daroussin const char **ap = a;
224d0ef721eSBaptiste Daroussin
225d0ef721eSBaptiste Daroussin li = el_line(el);
22691f76417SBaptiste Daroussin *ap = li->buffer;
227d0ef721eSBaptiste Daroussin }
228d0ef721eSBaptiste Daroussin
229d0ef721eSBaptiste Daroussin static const char *
_default_history_file(void)230d0ef721eSBaptiste Daroussin _default_history_file(void)
231d0ef721eSBaptiste Daroussin {
232d0ef721eSBaptiste Daroussin struct passwd *p;
233d0ef721eSBaptiste Daroussin static char *path;
234d0ef721eSBaptiste Daroussin size_t len;
235d0ef721eSBaptiste Daroussin
236d0ef721eSBaptiste Daroussin if (path)
237d0ef721eSBaptiste Daroussin return path;
238d0ef721eSBaptiste Daroussin
239d0ef721eSBaptiste Daroussin if ((p = getpwuid(getuid())) == NULL)
240d0ef721eSBaptiste Daroussin return NULL;
241d0ef721eSBaptiste Daroussin
242d0ef721eSBaptiste Daroussin len = strlen(p->pw_dir) + sizeof("/.history");
243*baff8195SBaptiste Daroussin if ((path = el_malloc(len)) == NULL)
244d0ef721eSBaptiste Daroussin return NULL;
245d0ef721eSBaptiste Daroussin
246d0ef721eSBaptiste Daroussin (void)snprintf(path, len, "%s/.history", p->pw_dir);
247d0ef721eSBaptiste Daroussin return path;
248d0ef721eSBaptiste Daroussin }
249d0ef721eSBaptiste Daroussin
250d0ef721eSBaptiste Daroussin /*
251d0ef721eSBaptiste Daroussin * READLINE compatibility stuff
252d0ef721eSBaptiste Daroussin */
253d0ef721eSBaptiste Daroussin
254d0ef721eSBaptiste Daroussin /*
255d0ef721eSBaptiste Daroussin * Set the prompt
256d0ef721eSBaptiste Daroussin */
257d0ef721eSBaptiste Daroussin int
rl_set_prompt(const char * prompt)258d0ef721eSBaptiste Daroussin rl_set_prompt(const char *prompt)
259d0ef721eSBaptiste Daroussin {
260d0ef721eSBaptiste Daroussin char *p;
261d0ef721eSBaptiste Daroussin
262d0ef721eSBaptiste Daroussin if (!prompt)
263d0ef721eSBaptiste Daroussin prompt = "";
264d0ef721eSBaptiste Daroussin if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
265d0ef721eSBaptiste Daroussin return 0;
266d0ef721eSBaptiste Daroussin if (rl_prompt)
267d0ef721eSBaptiste Daroussin el_free(rl_prompt);
268d0ef721eSBaptiste Daroussin rl_prompt = strdup(prompt);
269d0ef721eSBaptiste Daroussin if (rl_prompt == NULL)
270d0ef721eSBaptiste Daroussin return -1;
271d0ef721eSBaptiste Daroussin
272d0ef721eSBaptiste Daroussin while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) {
273d0ef721eSBaptiste Daroussin /* Remove adjacent end/start markers to avoid double-escapes. */
274d0ef721eSBaptiste Daroussin if (p[1] == RL_PROMPT_START_IGNORE) {
275d0ef721eSBaptiste Daroussin memmove(p, p + 2, 1 + strlen(p + 2));
276d0ef721eSBaptiste Daroussin } else {
277d0ef721eSBaptiste Daroussin *p = RL_PROMPT_START_IGNORE;
278d0ef721eSBaptiste Daroussin }
279d0ef721eSBaptiste Daroussin }
280d0ef721eSBaptiste Daroussin
281d0ef721eSBaptiste Daroussin return 0;
282d0ef721eSBaptiste Daroussin }
283d0ef721eSBaptiste Daroussin
2847f399375SBaptiste Daroussin void
rl_save_prompt(void)2857f399375SBaptiste Daroussin rl_save_prompt(void)
2867f399375SBaptiste Daroussin {
2877f399375SBaptiste Daroussin rl_prompt_saved = strdup(rl_prompt);
2887f399375SBaptiste Daroussin }
2897f399375SBaptiste Daroussin
2907f399375SBaptiste Daroussin void
rl_restore_prompt(void)2917f399375SBaptiste Daroussin rl_restore_prompt(void)
2927f399375SBaptiste Daroussin {
2937f399375SBaptiste Daroussin if (!rl_prompt_saved)
2947f399375SBaptiste Daroussin return;
2957f399375SBaptiste Daroussin rl_prompt = rl_prompt_saved;
2967f399375SBaptiste Daroussin rl_prompt_saved = NULL;
2977f399375SBaptiste Daroussin }
2987f399375SBaptiste Daroussin
299d0ef721eSBaptiste Daroussin /*
300d0ef721eSBaptiste Daroussin * initialize rl compat stuff
301d0ef721eSBaptiste Daroussin */
302d0ef721eSBaptiste Daroussin int
rl_initialize(void)303d0ef721eSBaptiste Daroussin rl_initialize(void)
304d0ef721eSBaptiste Daroussin {
305d0ef721eSBaptiste Daroussin HistEvent ev;
306d0ef721eSBaptiste Daroussin int editmode = 1;
307d0ef721eSBaptiste Daroussin struct termios t;
308d0ef721eSBaptiste Daroussin
309d0ef721eSBaptiste Daroussin if (e != NULL)
310d0ef721eSBaptiste Daroussin el_end(e);
311d0ef721eSBaptiste Daroussin if (h != NULL)
312d0ef721eSBaptiste Daroussin history_end(h);
313d0ef721eSBaptiste Daroussin
3147f399375SBaptiste Daroussin RL_UNSETSTATE(RL_STATE_DONE);
3157f399375SBaptiste Daroussin
316d0ef721eSBaptiste Daroussin if (!rl_instream)
317d0ef721eSBaptiste Daroussin rl_instream = stdin;
318d0ef721eSBaptiste Daroussin if (!rl_outstream)
319d0ef721eSBaptiste Daroussin rl_outstream = stdout;
320d0ef721eSBaptiste Daroussin
321d0ef721eSBaptiste Daroussin /*
322d0ef721eSBaptiste Daroussin * See if we don't really want to run the editor
323d0ef721eSBaptiste Daroussin */
324d0ef721eSBaptiste Daroussin if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
325d0ef721eSBaptiste Daroussin editmode = 0;
326d0ef721eSBaptiste Daroussin
327d0ef721eSBaptiste Daroussin e = el_init_internal(rl_readline_name, rl_instream, rl_outstream,
328d0ef721eSBaptiste Daroussin stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr),
329d0ef721eSBaptiste Daroussin NO_RESET);
330d0ef721eSBaptiste Daroussin
331d0ef721eSBaptiste Daroussin if (!editmode)
332d0ef721eSBaptiste Daroussin el_set(e, EL_EDITMODE, 0);
333d0ef721eSBaptiste Daroussin
334d0ef721eSBaptiste Daroussin h = history_init();
335d0ef721eSBaptiste Daroussin if (!e || !h)
336d0ef721eSBaptiste Daroussin return -1;
337d0ef721eSBaptiste Daroussin
338d0ef721eSBaptiste Daroussin history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
339d0ef721eSBaptiste Daroussin history_length = 0;
340d0ef721eSBaptiste Daroussin max_input_history = INT_MAX;
341d0ef721eSBaptiste Daroussin el_set(e, EL_HIST, history, h);
342d0ef721eSBaptiste Daroussin
343d0ef721eSBaptiste Daroussin /* Setup resize function */
344d0ef721eSBaptiste Daroussin el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer);
345d0ef721eSBaptiste Daroussin
346d0ef721eSBaptiste Daroussin /* setup getc function if valid */
347d0ef721eSBaptiste Daroussin if (rl_getc_function)
348d0ef721eSBaptiste Daroussin el_set(e, EL_GETCFN, _getc_function);
349d0ef721eSBaptiste Daroussin
350d0ef721eSBaptiste Daroussin /* for proper prompt printing in readline() */
351d0ef721eSBaptiste Daroussin if (rl_set_prompt("") == -1) {
352d0ef721eSBaptiste Daroussin history_end(h);
353d0ef721eSBaptiste Daroussin el_end(e);
354d0ef721eSBaptiste Daroussin return -1;
355d0ef721eSBaptiste Daroussin }
356d0ef721eSBaptiste Daroussin el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE);
357d0ef721eSBaptiste Daroussin el_set(e, EL_SIGNAL, rl_catch_signals);
358d0ef721eSBaptiste Daroussin
359d0ef721eSBaptiste Daroussin /* set default mode to "emacs"-style and read setting afterwards */
360d0ef721eSBaptiste Daroussin /* so this can be overridden */
361d0ef721eSBaptiste Daroussin el_set(e, EL_EDITOR, "emacs");
362d0ef721eSBaptiste Daroussin if (rl_terminal_name != NULL)
363d0ef721eSBaptiste Daroussin el_set(e, EL_TERMINAL, rl_terminal_name);
364d0ef721eSBaptiste Daroussin else
365d0ef721eSBaptiste Daroussin el_get(e, EL_TERMINAL, &rl_terminal_name);
366d0ef721eSBaptiste Daroussin
367d0ef721eSBaptiste Daroussin /*
368d0ef721eSBaptiste Daroussin * Word completion - this has to go AFTER rebinding keys
369d0ef721eSBaptiste Daroussin * to emacs-style.
370d0ef721eSBaptiste Daroussin */
371d0ef721eSBaptiste Daroussin el_set(e, EL_ADDFN, "rl_complete",
372d0ef721eSBaptiste Daroussin "ReadLine compatible completion function",
373d0ef721eSBaptiste Daroussin _el_rl_complete);
374d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "^I", "rl_complete", NULL);
375d0ef721eSBaptiste Daroussin
376d0ef721eSBaptiste Daroussin /*
377d0ef721eSBaptiste Daroussin * Send TSTP when ^Z is pressed.
378d0ef721eSBaptiste Daroussin */
379d0ef721eSBaptiste Daroussin el_set(e, EL_ADDFN, "rl_tstp",
380d0ef721eSBaptiste Daroussin "ReadLine compatible suspend function",
381d0ef721eSBaptiste Daroussin _el_rl_tstp);
382d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
383d0ef721eSBaptiste Daroussin
384d0ef721eSBaptiste Daroussin /*
385d0ef721eSBaptiste Daroussin * Set some readline compatible key-bindings.
386d0ef721eSBaptiste Daroussin */
387d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL);
388d0ef721eSBaptiste Daroussin
389d0ef721eSBaptiste Daroussin /*
390d0ef721eSBaptiste Daroussin * Allow the use of Home/End keys.
391d0ef721eSBaptiste Daroussin */
392d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
393d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
394d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL);
395d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL);
396d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL);
397d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL);
398d0ef721eSBaptiste Daroussin
399d0ef721eSBaptiste Daroussin /*
400d0ef721eSBaptiste Daroussin * Allow the use of the Delete/Insert keys.
401d0ef721eSBaptiste Daroussin */
402d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
403d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[2~", "ed-quoted-insert", NULL);
404d0ef721eSBaptiste Daroussin
405d0ef721eSBaptiste Daroussin /*
406d0ef721eSBaptiste Daroussin * Ctrl-left-arrow and Ctrl-right-arrow for word moving.
407d0ef721eSBaptiste Daroussin */
408d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
409d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
410d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL);
411d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL);
412d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
413d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
414d0ef721eSBaptiste Daroussin
415d0ef721eSBaptiste Daroussin /* read settings from configuration file */
416d0ef721eSBaptiste Daroussin el_source(e, NULL);
417d0ef721eSBaptiste Daroussin
418d0ef721eSBaptiste Daroussin /*
419d0ef721eSBaptiste Daroussin * Unfortunately, some applications really do use rl_point
420d0ef721eSBaptiste Daroussin * and rl_line_buffer directly.
421d0ef721eSBaptiste Daroussin */
422d0ef721eSBaptiste Daroussin _resize_fun(e, &rl_line_buffer);
423d0ef721eSBaptiste Daroussin _rl_update_pos();
424d0ef721eSBaptiste Daroussin
425d0ef721eSBaptiste Daroussin tty_end(e, TCSADRAIN);
426d0ef721eSBaptiste Daroussin
427d0ef721eSBaptiste Daroussin return 0;
428d0ef721eSBaptiste Daroussin }
429d0ef721eSBaptiste Daroussin
430d0ef721eSBaptiste Daroussin
431d0ef721eSBaptiste Daroussin /*
432d0ef721eSBaptiste Daroussin * read one line from input stream and return it, chomping
433d0ef721eSBaptiste Daroussin * trailing newline (if there is any)
434d0ef721eSBaptiste Daroussin */
435d0ef721eSBaptiste Daroussin char *
readline(const char * p)436d0ef721eSBaptiste Daroussin readline(const char *p)
437d0ef721eSBaptiste Daroussin {
438d0ef721eSBaptiste Daroussin HistEvent ev;
439d0ef721eSBaptiste Daroussin const char * volatile prompt = p;
440d0ef721eSBaptiste Daroussin int count;
441d0ef721eSBaptiste Daroussin const char *ret;
442d0ef721eSBaptiste Daroussin char *buf;
443d0ef721eSBaptiste Daroussin static int used_event_hook;
444d0ef721eSBaptiste Daroussin
445d0ef721eSBaptiste Daroussin if (e == NULL || h == NULL)
446d0ef721eSBaptiste Daroussin rl_initialize();
44791f76417SBaptiste Daroussin if (rl_startup_hook) {
4487f399375SBaptiste Daroussin (*rl_startup_hook)();
449d0ef721eSBaptiste Daroussin }
450d0ef721eSBaptiste Daroussin tty_init(e);
451d0ef721eSBaptiste Daroussin
452d0ef721eSBaptiste Daroussin
453d0ef721eSBaptiste Daroussin rl_done = 0;
454d0ef721eSBaptiste Daroussin
455d0ef721eSBaptiste Daroussin (void)setjmp(topbuf);
456d0ef721eSBaptiste Daroussin buf = NULL;
457d0ef721eSBaptiste Daroussin
458d0ef721eSBaptiste Daroussin /* update prompt accordingly to what has been passed */
459d0ef721eSBaptiste Daroussin if (rl_set_prompt(prompt) == -1)
460d0ef721eSBaptiste Daroussin goto out;
461d0ef721eSBaptiste Daroussin
462d0ef721eSBaptiste Daroussin if (rl_pre_input_hook)
4637f399375SBaptiste Daroussin (*rl_pre_input_hook)();
464d0ef721eSBaptiste Daroussin
465d0ef721eSBaptiste Daroussin if (rl_event_hook && !(e->el_flags & NO_TTY)) {
466d0ef721eSBaptiste Daroussin el_set(e, EL_GETCFN, _rl_event_read_char);
467d0ef721eSBaptiste Daroussin used_event_hook = 1;
468d0ef721eSBaptiste Daroussin }
469d0ef721eSBaptiste Daroussin
470d0ef721eSBaptiste Daroussin if (!rl_event_hook && used_event_hook) {
471d0ef721eSBaptiste Daroussin el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
472d0ef721eSBaptiste Daroussin used_event_hook = 0;
473d0ef721eSBaptiste Daroussin }
474d0ef721eSBaptiste Daroussin
475d0ef721eSBaptiste Daroussin rl_already_prompted = 0;
476d0ef721eSBaptiste Daroussin
477d0ef721eSBaptiste Daroussin /* get one line from input stream */
478d0ef721eSBaptiste Daroussin ret = el_gets(e, &count);
479d0ef721eSBaptiste Daroussin
480d0ef721eSBaptiste Daroussin if (ret && count > 0) {
481*baff8195SBaptiste Daroussin int lastidx;
482*baff8195SBaptiste Daroussin
483d0ef721eSBaptiste Daroussin buf = strdup(ret);
484d0ef721eSBaptiste Daroussin if (buf == NULL)
485d0ef721eSBaptiste Daroussin goto out;
486*baff8195SBaptiste Daroussin lastidx = count - 1;
487*baff8195SBaptiste Daroussin if (buf[lastidx] == '\n')
488*baff8195SBaptiste Daroussin buf[lastidx] = '\0';
489d0ef721eSBaptiste Daroussin } else
490d0ef721eSBaptiste Daroussin buf = NULL;
491d0ef721eSBaptiste Daroussin
492d0ef721eSBaptiste Daroussin history(h, &ev, H_GETSIZE);
493d0ef721eSBaptiste Daroussin history_length = ev.num;
494d0ef721eSBaptiste Daroussin
495d0ef721eSBaptiste Daroussin out:
496d0ef721eSBaptiste Daroussin tty_end(e, TCSADRAIN);
497d0ef721eSBaptiste Daroussin return buf;
498d0ef721eSBaptiste Daroussin }
499d0ef721eSBaptiste Daroussin
500d0ef721eSBaptiste Daroussin /*
501d0ef721eSBaptiste Daroussin * history functions
502d0ef721eSBaptiste Daroussin */
503d0ef721eSBaptiste Daroussin
504d0ef721eSBaptiste Daroussin /*
505d0ef721eSBaptiste Daroussin * is normally called before application starts to use
506d0ef721eSBaptiste Daroussin * history expansion functions
507d0ef721eSBaptiste Daroussin */
508d0ef721eSBaptiste Daroussin void
using_history(void)509d0ef721eSBaptiste Daroussin using_history(void)
510d0ef721eSBaptiste Daroussin {
511d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
512d0ef721eSBaptiste Daroussin rl_initialize();
513d0ef721eSBaptiste Daroussin history_offset = history_length;
514d0ef721eSBaptiste Daroussin }
515d0ef721eSBaptiste Daroussin
516d0ef721eSBaptiste Daroussin
517d0ef721eSBaptiste Daroussin /*
518d0ef721eSBaptiste Daroussin * substitute ``what'' with ``with'', returning resulting string; if
519d0ef721eSBaptiste Daroussin * globally == 1, substitutes all occurrences of what, otherwise only the
520d0ef721eSBaptiste Daroussin * first one
521d0ef721eSBaptiste Daroussin */
522d0ef721eSBaptiste Daroussin static char *
_rl_compat_sub(const char * str,const char * what,const char * with,int globally)523d0ef721eSBaptiste Daroussin _rl_compat_sub(const char *str, const char *what, const char *with,
524d0ef721eSBaptiste Daroussin int globally)
525d0ef721eSBaptiste Daroussin {
526d0ef721eSBaptiste Daroussin const char *s;
527d0ef721eSBaptiste Daroussin char *r, *result;
528d0ef721eSBaptiste Daroussin size_t len, with_len, what_len;
529d0ef721eSBaptiste Daroussin
530d0ef721eSBaptiste Daroussin len = strlen(str);
531d0ef721eSBaptiste Daroussin with_len = strlen(with);
532d0ef721eSBaptiste Daroussin what_len = strlen(what);
533d0ef721eSBaptiste Daroussin
534d0ef721eSBaptiste Daroussin /* calculate length we need for result */
535d0ef721eSBaptiste Daroussin s = str;
536d0ef721eSBaptiste Daroussin while (*s) {
537d0ef721eSBaptiste Daroussin if (*s == *what && !strncmp(s, what, what_len)) {
538d0ef721eSBaptiste Daroussin len += with_len - what_len;
539d0ef721eSBaptiste Daroussin if (!globally)
540d0ef721eSBaptiste Daroussin break;
541d0ef721eSBaptiste Daroussin s += what_len;
542d0ef721eSBaptiste Daroussin } else
543d0ef721eSBaptiste Daroussin s++;
544d0ef721eSBaptiste Daroussin }
545d0ef721eSBaptiste Daroussin r = result = el_calloc(len + 1, sizeof(*r));
546d0ef721eSBaptiste Daroussin if (result == NULL)
547d0ef721eSBaptiste Daroussin return NULL;
548d0ef721eSBaptiste Daroussin s = str;
549d0ef721eSBaptiste Daroussin while (*s) {
550d0ef721eSBaptiste Daroussin if (*s == *what && !strncmp(s, what, what_len)) {
551f9a159daSBaptiste Daroussin memcpy(r, with, with_len);
552d0ef721eSBaptiste Daroussin r += with_len;
553d0ef721eSBaptiste Daroussin s += what_len;
554d0ef721eSBaptiste Daroussin if (!globally) {
555d0ef721eSBaptiste Daroussin (void)strcpy(r, s);
556d0ef721eSBaptiste Daroussin return result;
557d0ef721eSBaptiste Daroussin }
558d0ef721eSBaptiste Daroussin } else
559d0ef721eSBaptiste Daroussin *r++ = *s++;
560d0ef721eSBaptiste Daroussin }
561d0ef721eSBaptiste Daroussin *r = '\0';
562d0ef721eSBaptiste Daroussin return result;
563d0ef721eSBaptiste Daroussin }
564d0ef721eSBaptiste Daroussin
565d0ef721eSBaptiste Daroussin static char *last_search_pat; /* last !?pat[?] search pattern */
566d0ef721eSBaptiste Daroussin static char *last_search_match; /* last !?pat[?] that matched */
567d0ef721eSBaptiste Daroussin
568d0ef721eSBaptiste Daroussin const char *
get_history_event(const char * cmd,int * cindex,int qchar)569d0ef721eSBaptiste Daroussin get_history_event(const char *cmd, int *cindex, int qchar)
570d0ef721eSBaptiste Daroussin {
571d0ef721eSBaptiste Daroussin int idx, sign, sub, num, begin, ret;
572d0ef721eSBaptiste Daroussin size_t len;
573d0ef721eSBaptiste Daroussin char *pat;
574d0ef721eSBaptiste Daroussin const char *rptr;
575d0ef721eSBaptiste Daroussin HistEvent ev;
576d0ef721eSBaptiste Daroussin
577d0ef721eSBaptiste Daroussin idx = *cindex;
578d0ef721eSBaptiste Daroussin if (cmd[idx++] != history_expansion_char)
579d0ef721eSBaptiste Daroussin return NULL;
580d0ef721eSBaptiste Daroussin
581d0ef721eSBaptiste Daroussin /* find out which event to take */
582d0ef721eSBaptiste Daroussin if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
583d0ef721eSBaptiste Daroussin if (history(h, &ev, H_FIRST) != 0)
584d0ef721eSBaptiste Daroussin return NULL;
585d0ef721eSBaptiste Daroussin *cindex = cmd[idx]? (idx + 1):idx;
586d0ef721eSBaptiste Daroussin return ev.str;
587d0ef721eSBaptiste Daroussin }
588d0ef721eSBaptiste Daroussin sign = 0;
589d0ef721eSBaptiste Daroussin if (cmd[idx] == '-') {
590d0ef721eSBaptiste Daroussin sign = 1;
591d0ef721eSBaptiste Daroussin idx++;
592d0ef721eSBaptiste Daroussin }
593d0ef721eSBaptiste Daroussin
594d0ef721eSBaptiste Daroussin if ('0' <= cmd[idx] && cmd[idx] <= '9') {
595d0ef721eSBaptiste Daroussin HIST_ENTRY *he;
596d0ef721eSBaptiste Daroussin
597d0ef721eSBaptiste Daroussin num = 0;
598d0ef721eSBaptiste Daroussin while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
599d0ef721eSBaptiste Daroussin num = num * 10 + cmd[idx] - '0';
600d0ef721eSBaptiste Daroussin idx++;
601d0ef721eSBaptiste Daroussin }
602d0ef721eSBaptiste Daroussin if (sign)
603d0ef721eSBaptiste Daroussin num = history_length - num + history_base;
604d0ef721eSBaptiste Daroussin
605d0ef721eSBaptiste Daroussin if (!(he = history_get(num)))
606d0ef721eSBaptiste Daroussin return NULL;
607d0ef721eSBaptiste Daroussin
608d0ef721eSBaptiste Daroussin *cindex = idx;
609d0ef721eSBaptiste Daroussin return he->line;
610d0ef721eSBaptiste Daroussin }
611d0ef721eSBaptiste Daroussin sub = 0;
612d0ef721eSBaptiste Daroussin if (cmd[idx] == '?') {
613d0ef721eSBaptiste Daroussin sub = 1;
614d0ef721eSBaptiste Daroussin idx++;
615d0ef721eSBaptiste Daroussin }
616d0ef721eSBaptiste Daroussin begin = idx;
617d0ef721eSBaptiste Daroussin while (cmd[idx]) {
618d0ef721eSBaptiste Daroussin if (cmd[idx] == '\n')
619d0ef721eSBaptiste Daroussin break;
620d0ef721eSBaptiste Daroussin if (sub && cmd[idx] == '?')
621d0ef721eSBaptiste Daroussin break;
622d0ef721eSBaptiste Daroussin if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
623d0ef721eSBaptiste Daroussin || cmd[idx] == '\t' || cmd[idx] == qchar))
624d0ef721eSBaptiste Daroussin break;
625d0ef721eSBaptiste Daroussin idx++;
626d0ef721eSBaptiste Daroussin }
627d0ef721eSBaptiste Daroussin len = (size_t)idx - (size_t)begin;
628d0ef721eSBaptiste Daroussin if (sub && cmd[idx] == '?')
629d0ef721eSBaptiste Daroussin idx++;
630d0ef721eSBaptiste Daroussin if (sub && len == 0 && last_search_pat && *last_search_pat)
631d0ef721eSBaptiste Daroussin pat = last_search_pat;
632d0ef721eSBaptiste Daroussin else if (len == 0)
633d0ef721eSBaptiste Daroussin return NULL;
634d0ef721eSBaptiste Daroussin else {
635d0ef721eSBaptiste Daroussin if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL)
636d0ef721eSBaptiste Daroussin return NULL;
637f9a159daSBaptiste Daroussin (void)strlcpy(pat, cmd + begin, len + 1);
638d0ef721eSBaptiste Daroussin }
639d0ef721eSBaptiste Daroussin
640d0ef721eSBaptiste Daroussin if (history(h, &ev, H_CURR) != 0) {
641d0ef721eSBaptiste Daroussin if (pat != last_search_pat)
642d0ef721eSBaptiste Daroussin el_free(pat);
643d0ef721eSBaptiste Daroussin return NULL;
644d0ef721eSBaptiste Daroussin }
645d0ef721eSBaptiste Daroussin num = ev.num;
646d0ef721eSBaptiste Daroussin
647d0ef721eSBaptiste Daroussin if (sub) {
648d0ef721eSBaptiste Daroussin if (pat != last_search_pat) {
649d0ef721eSBaptiste Daroussin el_free(last_search_pat);
650d0ef721eSBaptiste Daroussin last_search_pat = pat;
651d0ef721eSBaptiste Daroussin }
652d0ef721eSBaptiste Daroussin ret = history_search(pat, -1);
653d0ef721eSBaptiste Daroussin } else
654d0ef721eSBaptiste Daroussin ret = history_search_prefix(pat, -1);
655d0ef721eSBaptiste Daroussin
656d0ef721eSBaptiste Daroussin if (ret == -1) {
657d0ef721eSBaptiste Daroussin /* restore to end of list on failed search */
658d0ef721eSBaptiste Daroussin history(h, &ev, H_FIRST);
659d0ef721eSBaptiste Daroussin (void)fprintf(rl_outstream, "%s: Event not found\n", pat);
660d0ef721eSBaptiste Daroussin if (pat != last_search_pat)
661d0ef721eSBaptiste Daroussin el_free(pat);
662d0ef721eSBaptiste Daroussin return NULL;
663d0ef721eSBaptiste Daroussin }
664d0ef721eSBaptiste Daroussin
665d0ef721eSBaptiste Daroussin if (sub && len) {
666d0ef721eSBaptiste Daroussin el_free(last_search_match);
66791f76417SBaptiste Daroussin last_search_match = strdup(pat);
668d0ef721eSBaptiste Daroussin }
669d0ef721eSBaptiste Daroussin
670d0ef721eSBaptiste Daroussin if (pat != last_search_pat)
671d0ef721eSBaptiste Daroussin el_free(pat);
672d0ef721eSBaptiste Daroussin
673d0ef721eSBaptiste Daroussin if (history(h, &ev, H_CURR) != 0)
674d0ef721eSBaptiste Daroussin return NULL;
675d0ef721eSBaptiste Daroussin *cindex = idx;
676d0ef721eSBaptiste Daroussin rptr = ev.str;
677d0ef721eSBaptiste Daroussin
678d0ef721eSBaptiste Daroussin /* roll back to original position */
679d0ef721eSBaptiste Daroussin (void)history(h, &ev, H_SET, num);
680d0ef721eSBaptiste Daroussin
681d0ef721eSBaptiste Daroussin return rptr;
682d0ef721eSBaptiste Daroussin }
683d0ef721eSBaptiste Daroussin
68491f76417SBaptiste Daroussin static int
getfrom(const char ** cmdp,char ** fromp,const char * search,int delim)68591f76417SBaptiste Daroussin getfrom(const char **cmdp, char **fromp, const char *search, int delim)
68691f76417SBaptiste Daroussin {
68791f76417SBaptiste Daroussin size_t size = 16;
68891f76417SBaptiste Daroussin size_t len = 0;
68991f76417SBaptiste Daroussin const char *cmd = *cmdp;
69091f76417SBaptiste Daroussin char *what = el_realloc(*fromp, size * sizeof(*what));
69191f76417SBaptiste Daroussin if (what == NULL){
69291f76417SBaptiste Daroussin el_free(*fromp);
69391f76417SBaptiste Daroussin *fromp = NULL;
69491f76417SBaptiste Daroussin return 0;
69591f76417SBaptiste Daroussin }
69691f76417SBaptiste Daroussin for (; *cmd && *cmd != delim; cmd++) {
69791f76417SBaptiste Daroussin if (*cmd == '\\' && cmd[1] == delim)
69891f76417SBaptiste Daroussin cmd++;
69991f76417SBaptiste Daroussin if (len - 1 >= size) {
70091f76417SBaptiste Daroussin char *nwhat;
70191f76417SBaptiste Daroussin nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat));
70291f76417SBaptiste Daroussin if (nwhat == NULL) {
70391f76417SBaptiste Daroussin el_free(what);
70491f76417SBaptiste Daroussin el_free(*fromp);
70591f76417SBaptiste Daroussin *cmdp = cmd;
70691f76417SBaptiste Daroussin *fromp = NULL;
70791f76417SBaptiste Daroussin return 0;
70891f76417SBaptiste Daroussin }
70991f76417SBaptiste Daroussin what = nwhat;
71091f76417SBaptiste Daroussin }
71191f76417SBaptiste Daroussin what[len++] = *cmd;
71291f76417SBaptiste Daroussin }
71391f76417SBaptiste Daroussin what[len] = '\0';
71491f76417SBaptiste Daroussin *fromp = what;
71591f76417SBaptiste Daroussin *cmdp = cmd;
71691f76417SBaptiste Daroussin if (*what == '\0') {
71791f76417SBaptiste Daroussin el_free(what);
71891f76417SBaptiste Daroussin if (search) {
71991f76417SBaptiste Daroussin *fromp = strdup(search);
72091f76417SBaptiste Daroussin if (*fromp == NULL) {
72191f76417SBaptiste Daroussin return 0;
72291f76417SBaptiste Daroussin }
72391f76417SBaptiste Daroussin } else {
72491f76417SBaptiste Daroussin *fromp = NULL;
72591f76417SBaptiste Daroussin return -1;
72691f76417SBaptiste Daroussin }
72791f76417SBaptiste Daroussin }
72891f76417SBaptiste Daroussin if (!*cmd) {
72991f76417SBaptiste Daroussin el_free(what);
73091f76417SBaptiste Daroussin *fromp = NULL;
73191f76417SBaptiste Daroussin return -1;
73291f76417SBaptiste Daroussin }
73391f76417SBaptiste Daroussin
73491f76417SBaptiste Daroussin cmd++; /* shift after delim */
73591f76417SBaptiste Daroussin *cmdp = cmd;
73691f76417SBaptiste Daroussin
73791f76417SBaptiste Daroussin if (!*cmd) {
73891f76417SBaptiste Daroussin el_free(what);
73991f76417SBaptiste Daroussin *fromp = NULL;
74091f76417SBaptiste Daroussin return -1;
74191f76417SBaptiste Daroussin }
74291f76417SBaptiste Daroussin return 1;
74391f76417SBaptiste Daroussin }
74491f76417SBaptiste Daroussin
74591f76417SBaptiste Daroussin static int
getto(const char ** cmdp,char ** top,const char * from,int delim)74691f76417SBaptiste Daroussin getto(const char **cmdp, char **top, const char *from, int delim)
74791f76417SBaptiste Daroussin {
74891f76417SBaptiste Daroussin size_t size = 16;
74991f76417SBaptiste Daroussin size_t len = 0;
75091f76417SBaptiste Daroussin size_t from_len = strlen(from);
75191f76417SBaptiste Daroussin const char *cmd = *cmdp;
75291f76417SBaptiste Daroussin char *with = el_realloc(*top, size * sizeof(*with));
75391f76417SBaptiste Daroussin *top = NULL;
75491f76417SBaptiste Daroussin if (with == NULL)
75591f76417SBaptiste Daroussin goto out;
75691f76417SBaptiste Daroussin
75791f76417SBaptiste Daroussin for (; *cmd && *cmd != delim; cmd++) {
75891f76417SBaptiste Daroussin if (len + from_len + 1 >= size) {
75991f76417SBaptiste Daroussin char *nwith;
76091f76417SBaptiste Daroussin size += from_len + 1;
76191f76417SBaptiste Daroussin nwith = el_realloc(with, size * sizeof(*nwith));
76291f76417SBaptiste Daroussin if (nwith == NULL)
76391f76417SBaptiste Daroussin goto out;
76491f76417SBaptiste Daroussin with = nwith;
76591f76417SBaptiste Daroussin }
76691f76417SBaptiste Daroussin if (*cmd == '&') {
76791f76417SBaptiste Daroussin /* safe */
76891f76417SBaptiste Daroussin strcpy(&with[len], from);
76991f76417SBaptiste Daroussin len += from_len;
77091f76417SBaptiste Daroussin continue;
77191f76417SBaptiste Daroussin }
77291f76417SBaptiste Daroussin if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&'))
77391f76417SBaptiste Daroussin cmd++;
77491f76417SBaptiste Daroussin with[len++] = *cmd;
77591f76417SBaptiste Daroussin }
77691f76417SBaptiste Daroussin if (!*cmd)
77791f76417SBaptiste Daroussin goto out;
77891f76417SBaptiste Daroussin with[len] = '\0';
77991f76417SBaptiste Daroussin *top = with;
78091f76417SBaptiste Daroussin *cmdp = cmd;
78191f76417SBaptiste Daroussin return 1;
78291f76417SBaptiste Daroussin out:
78391f76417SBaptiste Daroussin el_free(with);
78491f76417SBaptiste Daroussin el_free(*top);
78591f76417SBaptiste Daroussin *top = NULL;
78691f76417SBaptiste Daroussin *cmdp = cmd;
78791f76417SBaptiste Daroussin return -1;
78891f76417SBaptiste Daroussin }
78991f76417SBaptiste Daroussin
79091f76417SBaptiste Daroussin static void
replace(char ** tmp,int c)79191f76417SBaptiste Daroussin replace(char **tmp, int c)
79291f76417SBaptiste Daroussin {
79391f76417SBaptiste Daroussin char *aptr;
79491f76417SBaptiste Daroussin if ((aptr = strrchr(*tmp, c)) == NULL)
79591f76417SBaptiste Daroussin return;
79691f76417SBaptiste Daroussin aptr = strdup(aptr + 1); // XXX: check
79791f76417SBaptiste Daroussin el_free(*tmp);
79891f76417SBaptiste Daroussin *tmp = aptr;
79991f76417SBaptiste Daroussin }
80091f76417SBaptiste Daroussin
801d0ef721eSBaptiste Daroussin /*
802d0ef721eSBaptiste Daroussin * the real function doing history expansion - takes as argument command
803d0ef721eSBaptiste Daroussin * to do and data upon which the command should be executed
804d0ef721eSBaptiste Daroussin * does expansion the way I've understood readline documentation
805d0ef721eSBaptiste Daroussin *
806d0ef721eSBaptiste Daroussin * returns 0 if data was not modified, 1 if it was and 2 if the string
807d0ef721eSBaptiste Daroussin * should be only printed and not executed; in case of error,
808d0ef721eSBaptiste Daroussin * returns -1 and *result points to NULL
809d0ef721eSBaptiste Daroussin * it's the caller's responsibility to free() the string returned in *result
810d0ef721eSBaptiste Daroussin */
811d0ef721eSBaptiste Daroussin static int
_history_expand_command(const char * command,size_t offs,size_t cmdlen,char ** result)812d0ef721eSBaptiste Daroussin _history_expand_command(const char *command, size_t offs, size_t cmdlen,
813d0ef721eSBaptiste Daroussin char **result)
814d0ef721eSBaptiste Daroussin {
81591f76417SBaptiste Daroussin char *tmp, *search = NULL, *aptr, delim;
816d0ef721eSBaptiste Daroussin const char *ptr, *cmd;
817d0ef721eSBaptiste Daroussin static char *from = NULL, *to = NULL;
818d0ef721eSBaptiste Daroussin int start, end, idx, has_mods = 0;
81991f76417SBaptiste Daroussin int p_on = 0, g_on = 0, ev;
820d0ef721eSBaptiste Daroussin
821d0ef721eSBaptiste Daroussin *result = NULL;
822d0ef721eSBaptiste Daroussin aptr = NULL;
823d0ef721eSBaptiste Daroussin ptr = NULL;
824d0ef721eSBaptiste Daroussin
825d0ef721eSBaptiste Daroussin /* First get event specifier */
826d0ef721eSBaptiste Daroussin idx = 0;
827d0ef721eSBaptiste Daroussin
828d0ef721eSBaptiste Daroussin if (strchr(":^*$", command[offs + 1])) {
829d0ef721eSBaptiste Daroussin char str[4];
830d0ef721eSBaptiste Daroussin /*
831d0ef721eSBaptiste Daroussin * "!:" is shorthand for "!!:".
832d0ef721eSBaptiste Daroussin * "!^", "!*" and "!$" are shorthand for
833d0ef721eSBaptiste Daroussin * "!!:^", "!!:*" and "!!:$" respectively.
834d0ef721eSBaptiste Daroussin */
835d0ef721eSBaptiste Daroussin str[0] = str[1] = '!';
836d0ef721eSBaptiste Daroussin str[2] = '0';
837d0ef721eSBaptiste Daroussin ptr = get_history_event(str, &idx, 0);
838d0ef721eSBaptiste Daroussin idx = (command[offs + 1] == ':')? 1:0;
839d0ef721eSBaptiste Daroussin has_mods = 1;
840d0ef721eSBaptiste Daroussin } else {
841d0ef721eSBaptiste Daroussin if (command[offs + 1] == '#') {
842d0ef721eSBaptiste Daroussin /* use command so far */
843d0ef721eSBaptiste Daroussin if ((aptr = el_calloc(offs + 1, sizeof(*aptr)))
844d0ef721eSBaptiste Daroussin == NULL)
845d0ef721eSBaptiste Daroussin return -1;
846f9a159daSBaptiste Daroussin (void)strlcpy(aptr, command, offs + 1);
847d0ef721eSBaptiste Daroussin idx = 1;
848d0ef721eSBaptiste Daroussin } else {
849d0ef721eSBaptiste Daroussin int qchar;
850d0ef721eSBaptiste Daroussin
85191f76417SBaptiste Daroussin qchar = (offs > 0 && command[offs - 1] == '"')
85291f76417SBaptiste Daroussin ? '"' : '\0';
853d0ef721eSBaptiste Daroussin ptr = get_history_event(command + offs, &idx, qchar);
854d0ef721eSBaptiste Daroussin }
855d0ef721eSBaptiste Daroussin has_mods = command[offs + (size_t)idx] == ':';
856d0ef721eSBaptiste Daroussin }
857d0ef721eSBaptiste Daroussin
858d0ef721eSBaptiste Daroussin if (ptr == NULL && aptr == NULL)
859d0ef721eSBaptiste Daroussin return -1;
860d0ef721eSBaptiste Daroussin
861d0ef721eSBaptiste Daroussin if (!has_mods) {
862d0ef721eSBaptiste Daroussin *result = strdup(aptr ? aptr : ptr);
863d0ef721eSBaptiste Daroussin if (aptr)
864d0ef721eSBaptiste Daroussin el_free(aptr);
865d0ef721eSBaptiste Daroussin if (*result == NULL)
866d0ef721eSBaptiste Daroussin return -1;
867d0ef721eSBaptiste Daroussin return 1;
868d0ef721eSBaptiste Daroussin }
869d0ef721eSBaptiste Daroussin
870d0ef721eSBaptiste Daroussin cmd = command + offs + idx + 1;
871d0ef721eSBaptiste Daroussin
872d0ef721eSBaptiste Daroussin /* Now parse any word designators */
873d0ef721eSBaptiste Daroussin
874d0ef721eSBaptiste Daroussin if (*cmd == '%') /* last word matched by ?pat? */
875d0ef721eSBaptiste Daroussin tmp = strdup(last_search_match ? last_search_match : "");
876d0ef721eSBaptiste Daroussin else if (strchr("^*$-0123456789", *cmd)) {
877d0ef721eSBaptiste Daroussin start = end = -1;
878d0ef721eSBaptiste Daroussin if (*cmd == '^')
879d0ef721eSBaptiste Daroussin start = end = 1, cmd++;
880d0ef721eSBaptiste Daroussin else if (*cmd == '$')
881d0ef721eSBaptiste Daroussin start = -1, cmd++;
882d0ef721eSBaptiste Daroussin else if (*cmd == '*')
883d0ef721eSBaptiste Daroussin start = 1, cmd++;
884d0ef721eSBaptiste Daroussin else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
885d0ef721eSBaptiste Daroussin start = 0;
886d0ef721eSBaptiste Daroussin while (*cmd && '0' <= *cmd && *cmd <= '9')
887d0ef721eSBaptiste Daroussin start = start * 10 + *cmd++ - '0';
888d0ef721eSBaptiste Daroussin
889d0ef721eSBaptiste Daroussin if (*cmd == '-') {
890d0ef721eSBaptiste Daroussin if (isdigit((unsigned char) cmd[1])) {
891d0ef721eSBaptiste Daroussin cmd++;
892d0ef721eSBaptiste Daroussin end = 0;
893d0ef721eSBaptiste Daroussin while (*cmd && '0' <= *cmd && *cmd <= '9')
894d0ef721eSBaptiste Daroussin end = end * 10 + *cmd++ - '0';
895d0ef721eSBaptiste Daroussin } else if (cmd[1] == '$') {
896d0ef721eSBaptiste Daroussin cmd += 2;
897d0ef721eSBaptiste Daroussin end = -1;
898d0ef721eSBaptiste Daroussin } else {
899d0ef721eSBaptiste Daroussin cmd++;
900d0ef721eSBaptiste Daroussin end = -2;
901d0ef721eSBaptiste Daroussin }
902d0ef721eSBaptiste Daroussin } else if (*cmd == '*')
903d0ef721eSBaptiste Daroussin end = -1, cmd++;
904d0ef721eSBaptiste Daroussin else
905d0ef721eSBaptiste Daroussin end = start;
906d0ef721eSBaptiste Daroussin }
907d0ef721eSBaptiste Daroussin tmp = history_arg_extract(start, end, aptr? aptr:ptr);
908d0ef721eSBaptiste Daroussin if (tmp == NULL) {
909d0ef721eSBaptiste Daroussin (void)fprintf(rl_outstream, "%s: Bad word specifier",
910d0ef721eSBaptiste Daroussin command + offs + idx);
911d0ef721eSBaptiste Daroussin if (aptr)
912d0ef721eSBaptiste Daroussin el_free(aptr);
913d0ef721eSBaptiste Daroussin return -1;
914d0ef721eSBaptiste Daroussin }
915d0ef721eSBaptiste Daroussin } else
916d0ef721eSBaptiste Daroussin tmp = strdup(aptr? aptr:ptr);
917d0ef721eSBaptiste Daroussin
918d0ef721eSBaptiste Daroussin if (aptr)
919d0ef721eSBaptiste Daroussin el_free(aptr);
920d0ef721eSBaptiste Daroussin
921d0ef721eSBaptiste Daroussin if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
922d0ef721eSBaptiste Daroussin *result = tmp;
923d0ef721eSBaptiste Daroussin return 1;
924d0ef721eSBaptiste Daroussin }
925d0ef721eSBaptiste Daroussin
926d0ef721eSBaptiste Daroussin for (; *cmd; cmd++) {
92791f76417SBaptiste Daroussin switch (*cmd) {
92891f76417SBaptiste Daroussin case ':':
929d0ef721eSBaptiste Daroussin continue;
93091f76417SBaptiste Daroussin case 'h': /* remove trailing path */
931d0ef721eSBaptiste Daroussin if ((aptr = strrchr(tmp, '/')) != NULL)
932d0ef721eSBaptiste Daroussin *aptr = '\0';
93391f76417SBaptiste Daroussin continue;
93491f76417SBaptiste Daroussin case 't': /* remove leading path */
93591f76417SBaptiste Daroussin replace(&tmp, '/');
93691f76417SBaptiste Daroussin continue;
93791f76417SBaptiste Daroussin case 'r': /* remove trailing suffix */
938d0ef721eSBaptiste Daroussin if ((aptr = strrchr(tmp, '.')) != NULL)
939d0ef721eSBaptiste Daroussin *aptr = '\0';
94091f76417SBaptiste Daroussin continue;
94191f76417SBaptiste Daroussin case 'e': /* remove all but suffix */
94291f76417SBaptiste Daroussin replace(&tmp, '.');
94391f76417SBaptiste Daroussin continue;
94491f76417SBaptiste Daroussin case 'p': /* print only */
945d0ef721eSBaptiste Daroussin p_on = 1;
94691f76417SBaptiste Daroussin continue;
94791f76417SBaptiste Daroussin case 'g':
948d0ef721eSBaptiste Daroussin g_on = 2;
949d0ef721eSBaptiste Daroussin continue;
95091f76417SBaptiste Daroussin case '&':
95191f76417SBaptiste Daroussin if (from == NULL || to == NULL)
952d0ef721eSBaptiste Daroussin continue;
95391f76417SBaptiste Daroussin /*FALLTHROUGH*/
95491f76417SBaptiste Daroussin case 's':
95591f76417SBaptiste Daroussin ev = -1;
95691f76417SBaptiste Daroussin delim = *++cmd;
95791f76417SBaptiste Daroussin if (delim == '\0' || *++cmd == '\0')
95891f76417SBaptiste Daroussin goto out;
95991f76417SBaptiste Daroussin if ((ev = getfrom(&cmd, &from, search, delim)) != 1)
96091f76417SBaptiste Daroussin goto out;
96191f76417SBaptiste Daroussin if ((ev = getto(&cmd, &to, from, delim)) != 1)
96291f76417SBaptiste Daroussin goto out;
963d0ef721eSBaptiste Daroussin aptr = _rl_compat_sub(tmp, from, to, g_on);
964d0ef721eSBaptiste Daroussin if (aptr) {
965d0ef721eSBaptiste Daroussin el_free(tmp);
966d0ef721eSBaptiste Daroussin tmp = aptr;
967d0ef721eSBaptiste Daroussin }
968d0ef721eSBaptiste Daroussin g_on = 0;
96991f76417SBaptiste Daroussin cmd--;
97091f76417SBaptiste Daroussin continue;
971d0ef721eSBaptiste Daroussin }
972d0ef721eSBaptiste Daroussin }
973d0ef721eSBaptiste Daroussin *result = tmp;
974d0ef721eSBaptiste Daroussin return p_on ? 2 : 1;
97591f76417SBaptiste Daroussin out:
97691f76417SBaptiste Daroussin el_free(tmp);
97791f76417SBaptiste Daroussin return ev;
97891f76417SBaptiste Daroussin
979d0ef721eSBaptiste Daroussin }
980d0ef721eSBaptiste Daroussin
981d0ef721eSBaptiste Daroussin
982d0ef721eSBaptiste Daroussin /*
983d0ef721eSBaptiste Daroussin * csh-style history expansion
984d0ef721eSBaptiste Daroussin */
985d0ef721eSBaptiste Daroussin int
history_expand(char * str,char ** output)986d0ef721eSBaptiste Daroussin history_expand(char *str, char **output)
987d0ef721eSBaptiste Daroussin {
988d0ef721eSBaptiste Daroussin int ret = 0;
989d0ef721eSBaptiste Daroussin size_t idx, i, size;
990d0ef721eSBaptiste Daroussin char *tmp, *result;
991d0ef721eSBaptiste Daroussin
992d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
993d0ef721eSBaptiste Daroussin rl_initialize();
994d0ef721eSBaptiste Daroussin
995d0ef721eSBaptiste Daroussin if (history_expansion_char == 0) {
996d0ef721eSBaptiste Daroussin *output = strdup(str);
997d0ef721eSBaptiste Daroussin return 0;
998d0ef721eSBaptiste Daroussin }
999d0ef721eSBaptiste Daroussin
1000d0ef721eSBaptiste Daroussin *output = NULL;
1001d0ef721eSBaptiste Daroussin if (str[0] == history_subst_char) {
1002d0ef721eSBaptiste Daroussin /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
1003d0ef721eSBaptiste Daroussin *output = el_calloc(strlen(str) + 4 + 1, sizeof(**output));
1004d0ef721eSBaptiste Daroussin if (*output == NULL)
1005d0ef721eSBaptiste Daroussin return 0;
1006d0ef721eSBaptiste Daroussin (*output)[0] = (*output)[1] = history_expansion_char;
1007d0ef721eSBaptiste Daroussin (*output)[2] = ':';
1008d0ef721eSBaptiste Daroussin (*output)[3] = 's';
1009d0ef721eSBaptiste Daroussin (void)strcpy((*output) + 4, str);
1010d0ef721eSBaptiste Daroussin str = *output;
1011d0ef721eSBaptiste Daroussin } else {
1012d0ef721eSBaptiste Daroussin *output = strdup(str);
1013d0ef721eSBaptiste Daroussin if (*output == NULL)
1014d0ef721eSBaptiste Daroussin return 0;
1015d0ef721eSBaptiste Daroussin }
1016d0ef721eSBaptiste Daroussin
1017d0ef721eSBaptiste Daroussin #define ADD_STRING(what, len, fr) \
1018d0ef721eSBaptiste Daroussin { \
1019d0ef721eSBaptiste Daroussin if (idx + len + 1 > size) { \
1020d0ef721eSBaptiste Daroussin char *nresult = el_realloc(result, \
1021d0ef721eSBaptiste Daroussin (size += len + 1) * sizeof(*nresult)); \
1022d0ef721eSBaptiste Daroussin if (nresult == NULL) { \
1023d0ef721eSBaptiste Daroussin el_free(*output); \
102491f76417SBaptiste Daroussin el_free(fr); \
1025d0ef721eSBaptiste Daroussin return 0; \
1026d0ef721eSBaptiste Daroussin } \
1027d0ef721eSBaptiste Daroussin result = nresult; \
1028d0ef721eSBaptiste Daroussin } \
1029f9a159daSBaptiste Daroussin (void)strlcpy(&result[idx], what, len + 1); \
1030d0ef721eSBaptiste Daroussin idx += len; \
1031d0ef721eSBaptiste Daroussin }
1032d0ef721eSBaptiste Daroussin
1033d0ef721eSBaptiste Daroussin result = NULL;
1034d0ef721eSBaptiste Daroussin size = idx = 0;
1035d0ef721eSBaptiste Daroussin tmp = NULL;
1036d0ef721eSBaptiste Daroussin for (i = 0; str[i];) {
1037d0ef721eSBaptiste Daroussin int qchar, loop_again;
1038d0ef721eSBaptiste Daroussin size_t len, start, j;
1039d0ef721eSBaptiste Daroussin
1040d0ef721eSBaptiste Daroussin qchar = 0;
1041d0ef721eSBaptiste Daroussin loop_again = 1;
1042d0ef721eSBaptiste Daroussin start = j = i;
1043d0ef721eSBaptiste Daroussin loop:
1044d0ef721eSBaptiste Daroussin for (; str[j]; j++) {
1045d0ef721eSBaptiste Daroussin if (str[j] == '\\' &&
1046d0ef721eSBaptiste Daroussin str[j + 1] == history_expansion_char) {
1047d0ef721eSBaptiste Daroussin len = strlen(&str[j + 1]) + 1;
1048d0ef721eSBaptiste Daroussin memmove(&str[j], &str[j + 1], len);
1049d0ef721eSBaptiste Daroussin continue;
1050d0ef721eSBaptiste Daroussin }
1051d0ef721eSBaptiste Daroussin if (!loop_again) {
1052d0ef721eSBaptiste Daroussin if (isspace((unsigned char) str[j])
1053d0ef721eSBaptiste Daroussin || str[j] == qchar)
1054d0ef721eSBaptiste Daroussin break;
1055d0ef721eSBaptiste Daroussin }
1056d0ef721eSBaptiste Daroussin if (str[j] == history_expansion_char
1057d0ef721eSBaptiste Daroussin && !strchr(history_no_expand_chars, str[j + 1])
1058d0ef721eSBaptiste Daroussin && (!history_inhibit_expansion_function ||
1059d0ef721eSBaptiste Daroussin (*history_inhibit_expansion_function)(str,
1060d0ef721eSBaptiste Daroussin (int)j) == 0))
1061d0ef721eSBaptiste Daroussin break;
1062d0ef721eSBaptiste Daroussin }
1063d0ef721eSBaptiste Daroussin
1064d0ef721eSBaptiste Daroussin if (str[j] && loop_again) {
1065d0ef721eSBaptiste Daroussin i = j;
1066d0ef721eSBaptiste Daroussin qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
1067d0ef721eSBaptiste Daroussin j++;
1068d0ef721eSBaptiste Daroussin if (str[j] == history_expansion_char)
1069d0ef721eSBaptiste Daroussin j++;
1070d0ef721eSBaptiste Daroussin loop_again = 0;
1071d0ef721eSBaptiste Daroussin goto loop;
1072d0ef721eSBaptiste Daroussin }
1073d0ef721eSBaptiste Daroussin len = i - start;
107491f76417SBaptiste Daroussin ADD_STRING(&str[start], len, NULL);
1075d0ef721eSBaptiste Daroussin
1076d0ef721eSBaptiste Daroussin if (str[i] == '\0' || str[i] != history_expansion_char) {
1077d0ef721eSBaptiste Daroussin len = j - i;
107891f76417SBaptiste Daroussin ADD_STRING(&str[i], len, NULL);
1079d0ef721eSBaptiste Daroussin if (start == 0)
1080d0ef721eSBaptiste Daroussin ret = 0;
1081d0ef721eSBaptiste Daroussin else
1082d0ef721eSBaptiste Daroussin ret = 1;
1083d0ef721eSBaptiste Daroussin break;
1084d0ef721eSBaptiste Daroussin }
1085d0ef721eSBaptiste Daroussin ret = _history_expand_command (str, i, (j - i), &tmp);
1086d0ef721eSBaptiste Daroussin if (ret > 0 && tmp) {
1087d0ef721eSBaptiste Daroussin len = strlen(tmp);
108891f76417SBaptiste Daroussin ADD_STRING(tmp, len, tmp);
1089d0ef721eSBaptiste Daroussin }
1090d0ef721eSBaptiste Daroussin if (tmp) {
1091d0ef721eSBaptiste Daroussin el_free(tmp);
1092d0ef721eSBaptiste Daroussin tmp = NULL;
1093d0ef721eSBaptiste Daroussin }
1094d0ef721eSBaptiste Daroussin i = j;
1095d0ef721eSBaptiste Daroussin }
1096d0ef721eSBaptiste Daroussin
1097d0ef721eSBaptiste Daroussin /* ret is 2 for "print only" option */
1098d0ef721eSBaptiste Daroussin if (ret == 2) {
1099d0ef721eSBaptiste Daroussin add_history(result);
1100d0ef721eSBaptiste Daroussin #ifdef GDB_411_HACK
1101d0ef721eSBaptiste Daroussin /* gdb 4.11 has been shipped with readline, where */
1102d0ef721eSBaptiste Daroussin /* history_expand() returned -1 when the line */
1103d0ef721eSBaptiste Daroussin /* should not be executed; in readline 2.1+ */
1104d0ef721eSBaptiste Daroussin /* it should return 2 in such a case */
1105d0ef721eSBaptiste Daroussin ret = -1;
1106d0ef721eSBaptiste Daroussin #endif
1107d0ef721eSBaptiste Daroussin }
1108d0ef721eSBaptiste Daroussin el_free(*output);
1109d0ef721eSBaptiste Daroussin *output = result;
1110d0ef721eSBaptiste Daroussin
1111d0ef721eSBaptiste Daroussin return ret;
1112d0ef721eSBaptiste Daroussin }
1113d0ef721eSBaptiste Daroussin
1114d0ef721eSBaptiste Daroussin /*
1115d0ef721eSBaptiste Daroussin * Return a string consisting of arguments of "str" from "start" to "end".
1116d0ef721eSBaptiste Daroussin */
1117d0ef721eSBaptiste Daroussin char *
history_arg_extract(int start,int end,const char * str)1118d0ef721eSBaptiste Daroussin history_arg_extract(int start, int end, const char *str)
1119d0ef721eSBaptiste Daroussin {
1120d0ef721eSBaptiste Daroussin size_t i, len, max;
1121d0ef721eSBaptiste Daroussin char **arr, *result = NULL;
1122d0ef721eSBaptiste Daroussin
1123d0ef721eSBaptiste Daroussin arr = history_tokenize(str);
1124d0ef721eSBaptiste Daroussin if (!arr)
1125d0ef721eSBaptiste Daroussin return NULL;
1126d0ef721eSBaptiste Daroussin if (arr && *arr == NULL)
1127d0ef721eSBaptiste Daroussin goto out;
1128d0ef721eSBaptiste Daroussin
1129d0ef721eSBaptiste Daroussin for (max = 0; arr[max]; max++)
1130d0ef721eSBaptiste Daroussin continue;
1131d0ef721eSBaptiste Daroussin max--;
1132d0ef721eSBaptiste Daroussin
1133d0ef721eSBaptiste Daroussin if (start == '$')
1134d0ef721eSBaptiste Daroussin start = (int)max;
1135d0ef721eSBaptiste Daroussin if (end == '$')
1136d0ef721eSBaptiste Daroussin end = (int)max;
1137d0ef721eSBaptiste Daroussin if (end < 0)
1138d0ef721eSBaptiste Daroussin end = (int)max + end + 1;
1139d0ef721eSBaptiste Daroussin if (start < 0)
1140d0ef721eSBaptiste Daroussin start = end;
1141d0ef721eSBaptiste Daroussin
1142d0ef721eSBaptiste Daroussin if (start < 0 || end < 0 || (size_t)start > max ||
1143d0ef721eSBaptiste Daroussin (size_t)end > max || start > end)
1144d0ef721eSBaptiste Daroussin goto out;
1145d0ef721eSBaptiste Daroussin
1146d0ef721eSBaptiste Daroussin for (i = (size_t)start, len = 0; i <= (size_t)end; i++)
1147d0ef721eSBaptiste Daroussin len += strlen(arr[i]) + 1;
1148d0ef721eSBaptiste Daroussin len++;
1149d0ef721eSBaptiste Daroussin result = el_calloc(len, sizeof(*result));
1150d0ef721eSBaptiste Daroussin if (result == NULL)
1151d0ef721eSBaptiste Daroussin goto out;
1152d0ef721eSBaptiste Daroussin
1153d0ef721eSBaptiste Daroussin for (i = (size_t)start, len = 0; i <= (size_t)end; i++) {
1154d0ef721eSBaptiste Daroussin (void)strcpy(result + len, arr[i]);
1155d0ef721eSBaptiste Daroussin len += strlen(arr[i]);
1156d0ef721eSBaptiste Daroussin if (i < (size_t)end)
1157d0ef721eSBaptiste Daroussin result[len++] = ' ';
1158d0ef721eSBaptiste Daroussin }
1159d0ef721eSBaptiste Daroussin result[len] = '\0';
1160d0ef721eSBaptiste Daroussin
1161d0ef721eSBaptiste Daroussin out:
1162d0ef721eSBaptiste Daroussin for (i = 0; arr[i]; i++)
1163d0ef721eSBaptiste Daroussin el_free(arr[i]);
1164d0ef721eSBaptiste Daroussin el_free(arr);
1165d0ef721eSBaptiste Daroussin
1166d0ef721eSBaptiste Daroussin return result;
1167d0ef721eSBaptiste Daroussin }
1168d0ef721eSBaptiste Daroussin
1169d0ef721eSBaptiste Daroussin /*
1170d0ef721eSBaptiste Daroussin * Parse the string into individual tokens,
1171d0ef721eSBaptiste Daroussin * similar to how shell would do it.
1172d0ef721eSBaptiste Daroussin */
1173d0ef721eSBaptiste Daroussin char **
history_tokenize(const char * str)1174d0ef721eSBaptiste Daroussin history_tokenize(const char *str)
1175d0ef721eSBaptiste Daroussin {
1176d0ef721eSBaptiste Daroussin int size = 1, idx = 0, i, start;
1177d0ef721eSBaptiste Daroussin size_t len;
1178d0ef721eSBaptiste Daroussin char **result = NULL, *temp, delim = '\0';
1179d0ef721eSBaptiste Daroussin
1180d0ef721eSBaptiste Daroussin for (i = 0; str[i];) {
1181d0ef721eSBaptiste Daroussin while (isspace((unsigned char) str[i]))
1182d0ef721eSBaptiste Daroussin i++;
1183d0ef721eSBaptiste Daroussin start = i;
1184d0ef721eSBaptiste Daroussin for (; str[i];) {
1185d0ef721eSBaptiste Daroussin if (str[i] == '\\') {
1186d0ef721eSBaptiste Daroussin if (str[i+1] != '\0')
1187d0ef721eSBaptiste Daroussin i++;
1188d0ef721eSBaptiste Daroussin } else if (str[i] == delim)
1189d0ef721eSBaptiste Daroussin delim = '\0';
1190d0ef721eSBaptiste Daroussin else if (!delim &&
1191d0ef721eSBaptiste Daroussin (isspace((unsigned char) str[i]) ||
1192d0ef721eSBaptiste Daroussin strchr("()<>;&|$", str[i])))
1193d0ef721eSBaptiste Daroussin break;
1194d0ef721eSBaptiste Daroussin else if (!delim && strchr("'`\"", str[i]))
1195d0ef721eSBaptiste Daroussin delim = str[i];
1196d0ef721eSBaptiste Daroussin if (str[i])
1197d0ef721eSBaptiste Daroussin i++;
1198d0ef721eSBaptiste Daroussin }
1199d0ef721eSBaptiste Daroussin
1200d0ef721eSBaptiste Daroussin if (idx + 2 >= size) {
1201d0ef721eSBaptiste Daroussin char **nresult;
1202d0ef721eSBaptiste Daroussin size <<= 1;
1203d0ef721eSBaptiste Daroussin nresult = el_realloc(result, (size_t)size * sizeof(*nresult));
1204d0ef721eSBaptiste Daroussin if (nresult == NULL) {
1205d0ef721eSBaptiste Daroussin el_free(result);
1206d0ef721eSBaptiste Daroussin return NULL;
1207d0ef721eSBaptiste Daroussin }
1208d0ef721eSBaptiste Daroussin result = nresult;
1209d0ef721eSBaptiste Daroussin }
1210d0ef721eSBaptiste Daroussin len = (size_t)i - (size_t)start;
1211d0ef721eSBaptiste Daroussin temp = el_calloc(len + 1, sizeof(*temp));
1212d0ef721eSBaptiste Daroussin if (temp == NULL) {
1213d0ef721eSBaptiste Daroussin for (i = 0; i < idx; i++)
1214d0ef721eSBaptiste Daroussin el_free(result[i]);
1215d0ef721eSBaptiste Daroussin el_free(result);
1216d0ef721eSBaptiste Daroussin return NULL;
1217d0ef721eSBaptiste Daroussin }
1218f9a159daSBaptiste Daroussin (void)strlcpy(temp, &str[start], len + 1);
1219d0ef721eSBaptiste Daroussin result[idx++] = temp;
1220d0ef721eSBaptiste Daroussin result[idx] = NULL;
1221d0ef721eSBaptiste Daroussin if (str[i])
1222d0ef721eSBaptiste Daroussin i++;
1223d0ef721eSBaptiste Daroussin }
1224d0ef721eSBaptiste Daroussin return result;
1225d0ef721eSBaptiste Daroussin }
1226d0ef721eSBaptiste Daroussin
1227d0ef721eSBaptiste Daroussin
1228d0ef721eSBaptiste Daroussin /*
1229d0ef721eSBaptiste Daroussin * limit size of history record to ``max'' events
1230d0ef721eSBaptiste Daroussin */
1231d0ef721eSBaptiste Daroussin void
stifle_history(int max)1232d0ef721eSBaptiste Daroussin stifle_history(int max)
1233d0ef721eSBaptiste Daroussin {
1234d0ef721eSBaptiste Daroussin HistEvent ev;
1235d0ef721eSBaptiste Daroussin HIST_ENTRY *he;
1236d0ef721eSBaptiste Daroussin
1237d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1238d0ef721eSBaptiste Daroussin rl_initialize();
1239d0ef721eSBaptiste Daroussin
1240d0ef721eSBaptiste Daroussin if (history(h, &ev, H_SETSIZE, max) == 0) {
1241d0ef721eSBaptiste Daroussin max_input_history = max;
1242d0ef721eSBaptiste Daroussin if (history_length > max)
1243d0ef721eSBaptiste Daroussin history_base = history_length - max;
1244d0ef721eSBaptiste Daroussin while (history_length > max) {
1245d0ef721eSBaptiste Daroussin he = remove_history(0);
1246d0ef721eSBaptiste Daroussin el_free(he->data);
1247d0ef721eSBaptiste Daroussin el_free((void *)(unsigned long)he->line);
1248d0ef721eSBaptiste Daroussin el_free(he);
1249d0ef721eSBaptiste Daroussin }
1250d0ef721eSBaptiste Daroussin }
1251d0ef721eSBaptiste Daroussin }
1252d0ef721eSBaptiste Daroussin
1253d0ef721eSBaptiste Daroussin
1254d0ef721eSBaptiste Daroussin /*
1255d0ef721eSBaptiste Daroussin * "unlimit" size of history - set the limit to maximum allowed int value
1256d0ef721eSBaptiste Daroussin */
1257d0ef721eSBaptiste Daroussin int
unstifle_history(void)1258d0ef721eSBaptiste Daroussin unstifle_history(void)
1259d0ef721eSBaptiste Daroussin {
1260d0ef721eSBaptiste Daroussin HistEvent ev;
1261d0ef721eSBaptiste Daroussin int omax;
1262d0ef721eSBaptiste Daroussin
1263d0ef721eSBaptiste Daroussin history(h, &ev, H_SETSIZE, INT_MAX);
1264d0ef721eSBaptiste Daroussin omax = max_input_history;
1265d0ef721eSBaptiste Daroussin max_input_history = INT_MAX;
1266d0ef721eSBaptiste Daroussin return omax; /* some value _must_ be returned */
1267d0ef721eSBaptiste Daroussin }
1268d0ef721eSBaptiste Daroussin
1269d0ef721eSBaptiste Daroussin
1270d0ef721eSBaptiste Daroussin int
history_is_stifled(void)1271d0ef721eSBaptiste Daroussin history_is_stifled(void)
1272d0ef721eSBaptiste Daroussin {
1273d0ef721eSBaptiste Daroussin
1274d0ef721eSBaptiste Daroussin /* cannot return true answer */
1275d0ef721eSBaptiste Daroussin return max_input_history != INT_MAX;
1276d0ef721eSBaptiste Daroussin }
1277d0ef721eSBaptiste Daroussin
1278d0ef721eSBaptiste Daroussin static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
1279d0ef721eSBaptiste Daroussin
1280d0ef721eSBaptiste Daroussin int
history_truncate_file(const char * filename,int nlines)1281d0ef721eSBaptiste Daroussin history_truncate_file (const char *filename, int nlines)
1282d0ef721eSBaptiste Daroussin {
1283d0ef721eSBaptiste Daroussin int ret = 0;
1284d0ef721eSBaptiste Daroussin FILE *fp, *tp;
1285d0ef721eSBaptiste Daroussin char template[sizeof(_history_tmp_template)];
1286d0ef721eSBaptiste Daroussin char buf[4096];
1287d0ef721eSBaptiste Daroussin int fd;
1288d0ef721eSBaptiste Daroussin char *cp;
1289d0ef721eSBaptiste Daroussin off_t off;
1290d0ef721eSBaptiste Daroussin int count = 0;
1291d0ef721eSBaptiste Daroussin ssize_t left = 0;
1292d0ef721eSBaptiste Daroussin
1293d0ef721eSBaptiste Daroussin if (filename == NULL && (filename = _default_history_file()) == NULL)
1294d0ef721eSBaptiste Daroussin return errno;
1295d0ef721eSBaptiste Daroussin if ((fp = fopen(filename, "r+")) == NULL)
1296d0ef721eSBaptiste Daroussin return errno;
1297d0ef721eSBaptiste Daroussin strcpy(template, _history_tmp_template);
1298d0ef721eSBaptiste Daroussin if ((fd = mkstemp(template)) == -1) {
1299d0ef721eSBaptiste Daroussin ret = errno;
1300d0ef721eSBaptiste Daroussin goto out1;
1301d0ef721eSBaptiste Daroussin }
1302d0ef721eSBaptiste Daroussin
1303d0ef721eSBaptiste Daroussin if ((tp = fdopen(fd, "r+")) == NULL) {
1304d0ef721eSBaptiste Daroussin close(fd);
1305d0ef721eSBaptiste Daroussin ret = errno;
1306d0ef721eSBaptiste Daroussin goto out2;
1307d0ef721eSBaptiste Daroussin }
1308d0ef721eSBaptiste Daroussin
1309d0ef721eSBaptiste Daroussin for(;;) {
1310d0ef721eSBaptiste Daroussin if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) {
1311d0ef721eSBaptiste Daroussin if (ferror(fp)) {
1312d0ef721eSBaptiste Daroussin ret = errno;
1313d0ef721eSBaptiste Daroussin break;
1314d0ef721eSBaptiste Daroussin }
1315d0ef721eSBaptiste Daroussin if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
1316d0ef721eSBaptiste Daroussin (off_t)-1) {
1317d0ef721eSBaptiste Daroussin ret = errno;
1318d0ef721eSBaptiste Daroussin break;
1319d0ef721eSBaptiste Daroussin }
1320d0ef721eSBaptiste Daroussin left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp);
1321d0ef721eSBaptiste Daroussin if (ferror(fp)) {
1322d0ef721eSBaptiste Daroussin ret = errno;
1323d0ef721eSBaptiste Daroussin break;
1324d0ef721eSBaptiste Daroussin }
1325d0ef721eSBaptiste Daroussin if (left == 0) {
1326d0ef721eSBaptiste Daroussin count--;
1327d0ef721eSBaptiste Daroussin left = sizeof(buf);
1328d0ef721eSBaptiste Daroussin } else if (fwrite(buf, (size_t)left, (size_t)1, tp)
1329d0ef721eSBaptiste Daroussin != 1) {
1330d0ef721eSBaptiste Daroussin ret = errno;
1331d0ef721eSBaptiste Daroussin break;
1332d0ef721eSBaptiste Daroussin }
1333d0ef721eSBaptiste Daroussin fflush(tp);
1334d0ef721eSBaptiste Daroussin break;
1335d0ef721eSBaptiste Daroussin }
1336d0ef721eSBaptiste Daroussin if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) {
1337d0ef721eSBaptiste Daroussin ret = errno;
1338d0ef721eSBaptiste Daroussin break;
1339d0ef721eSBaptiste Daroussin }
1340d0ef721eSBaptiste Daroussin count++;
1341d0ef721eSBaptiste Daroussin }
1342d0ef721eSBaptiste Daroussin if (ret)
1343d0ef721eSBaptiste Daroussin goto out3;
1344d0ef721eSBaptiste Daroussin cp = buf + left - 1;
1345d0ef721eSBaptiste Daroussin if(*cp != '\n')
1346d0ef721eSBaptiste Daroussin cp++;
1347d0ef721eSBaptiste Daroussin for(;;) {
1348d0ef721eSBaptiste Daroussin while (--cp >= buf) {
1349d0ef721eSBaptiste Daroussin if (*cp == '\n') {
1350d0ef721eSBaptiste Daroussin if (--nlines == 0) {
1351d0ef721eSBaptiste Daroussin if (++cp >= buf + sizeof(buf)) {
1352d0ef721eSBaptiste Daroussin count++;
1353d0ef721eSBaptiste Daroussin cp = buf;
1354d0ef721eSBaptiste Daroussin }
1355d0ef721eSBaptiste Daroussin break;
1356d0ef721eSBaptiste Daroussin }
1357d0ef721eSBaptiste Daroussin }
1358d0ef721eSBaptiste Daroussin }
1359d0ef721eSBaptiste Daroussin if (nlines <= 0 || count == 0)
1360d0ef721eSBaptiste Daroussin break;
1361d0ef721eSBaptiste Daroussin count--;
1362d0ef721eSBaptiste Daroussin if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
1363d0ef721eSBaptiste Daroussin ret = errno;
1364d0ef721eSBaptiste Daroussin break;
1365d0ef721eSBaptiste Daroussin }
1366d0ef721eSBaptiste Daroussin if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) {
1367d0ef721eSBaptiste Daroussin if (ferror(tp)) {
1368d0ef721eSBaptiste Daroussin ret = errno;
1369d0ef721eSBaptiste Daroussin break;
1370d0ef721eSBaptiste Daroussin }
1371d0ef721eSBaptiste Daroussin ret = EAGAIN;
1372d0ef721eSBaptiste Daroussin break;
1373d0ef721eSBaptiste Daroussin }
1374d0ef721eSBaptiste Daroussin cp = buf + sizeof(buf);
1375d0ef721eSBaptiste Daroussin }
1376d0ef721eSBaptiste Daroussin
1377d0ef721eSBaptiste Daroussin if (ret || nlines > 0)
1378d0ef721eSBaptiste Daroussin goto out3;
1379d0ef721eSBaptiste Daroussin
1380d0ef721eSBaptiste Daroussin if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
1381d0ef721eSBaptiste Daroussin ret = errno;
1382d0ef721eSBaptiste Daroussin goto out3;
1383d0ef721eSBaptiste Daroussin }
1384d0ef721eSBaptiste Daroussin
1385d0ef721eSBaptiste Daroussin if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
1386d0ef721eSBaptiste Daroussin (off_t)-1) {
1387d0ef721eSBaptiste Daroussin ret = errno;
1388d0ef721eSBaptiste Daroussin goto out3;
1389d0ef721eSBaptiste Daroussin }
1390d0ef721eSBaptiste Daroussin
1391d0ef721eSBaptiste Daroussin for(;;) {
1392d0ef721eSBaptiste Daroussin if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) {
1393d0ef721eSBaptiste Daroussin if (ferror(fp))
1394d0ef721eSBaptiste Daroussin ret = errno;
1395d0ef721eSBaptiste Daroussin break;
1396d0ef721eSBaptiste Daroussin }
1397d0ef721eSBaptiste Daroussin if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) {
1398d0ef721eSBaptiste Daroussin ret = errno;
1399d0ef721eSBaptiste Daroussin break;
1400d0ef721eSBaptiste Daroussin }
1401d0ef721eSBaptiste Daroussin }
1402d0ef721eSBaptiste Daroussin fflush(fp);
1403d0ef721eSBaptiste Daroussin if((off = ftello(fp)) > 0)
1404d0ef721eSBaptiste Daroussin (void)ftruncate(fileno(fp), off);
1405d0ef721eSBaptiste Daroussin out3:
1406d0ef721eSBaptiste Daroussin fclose(tp);
1407d0ef721eSBaptiste Daroussin out2:
1408d0ef721eSBaptiste Daroussin unlink(template);
1409d0ef721eSBaptiste Daroussin out1:
1410d0ef721eSBaptiste Daroussin fclose(fp);
1411d0ef721eSBaptiste Daroussin
1412d0ef721eSBaptiste Daroussin return ret;
1413d0ef721eSBaptiste Daroussin }
1414d0ef721eSBaptiste Daroussin
1415d0ef721eSBaptiste Daroussin
1416d0ef721eSBaptiste Daroussin /*
1417d0ef721eSBaptiste Daroussin * read history from a file given
1418d0ef721eSBaptiste Daroussin */
1419d0ef721eSBaptiste Daroussin int
read_history(const char * filename)1420d0ef721eSBaptiste Daroussin read_history(const char *filename)
1421d0ef721eSBaptiste Daroussin {
1422d0ef721eSBaptiste Daroussin HistEvent ev;
1423d0ef721eSBaptiste Daroussin
1424d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1425d0ef721eSBaptiste Daroussin rl_initialize();
1426d0ef721eSBaptiste Daroussin if (filename == NULL && (filename = _default_history_file()) == NULL)
1427d0ef721eSBaptiste Daroussin return errno;
1428d0ef721eSBaptiste Daroussin errno = 0;
1429d0ef721eSBaptiste Daroussin if (history(h, &ev, H_LOAD, filename) == -1)
1430d0ef721eSBaptiste Daroussin return errno ? errno : EINVAL;
1431d0ef721eSBaptiste Daroussin if (history(h, &ev, H_GETSIZE) == 0)
1432d0ef721eSBaptiste Daroussin history_length = ev.num;
1433d0ef721eSBaptiste Daroussin if (history_length < 0)
1434d0ef721eSBaptiste Daroussin return EINVAL;
1435d0ef721eSBaptiste Daroussin return 0;
1436d0ef721eSBaptiste Daroussin }
1437d0ef721eSBaptiste Daroussin
1438d0ef721eSBaptiste Daroussin
1439d0ef721eSBaptiste Daroussin /*
1440d0ef721eSBaptiste Daroussin * write history to a file given
1441d0ef721eSBaptiste Daroussin */
1442d0ef721eSBaptiste Daroussin int
write_history(const char * filename)1443d0ef721eSBaptiste Daroussin write_history(const char *filename)
1444d0ef721eSBaptiste Daroussin {
1445d0ef721eSBaptiste Daroussin HistEvent ev;
1446d0ef721eSBaptiste Daroussin
1447d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1448d0ef721eSBaptiste Daroussin rl_initialize();
1449d0ef721eSBaptiste Daroussin if (filename == NULL && (filename = _default_history_file()) == NULL)
1450d0ef721eSBaptiste Daroussin return errno;
1451d0ef721eSBaptiste Daroussin return history(h, &ev, H_SAVE, filename) == -1 ?
1452d0ef721eSBaptiste Daroussin (errno ? errno : EINVAL) : 0;
1453d0ef721eSBaptiste Daroussin }
1454d0ef721eSBaptiste Daroussin
1455d0ef721eSBaptiste Daroussin int
append_history(int n,const char * filename)1456d0ef721eSBaptiste Daroussin append_history(int n, const char *filename)
1457d0ef721eSBaptiste Daroussin {
1458d0ef721eSBaptiste Daroussin HistEvent ev;
1459d0ef721eSBaptiste Daroussin FILE *fp;
1460d0ef721eSBaptiste Daroussin
1461d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1462d0ef721eSBaptiste Daroussin rl_initialize();
1463d0ef721eSBaptiste Daroussin if (filename == NULL && (filename = _default_history_file()) == NULL)
1464d0ef721eSBaptiste Daroussin return errno;
1465d0ef721eSBaptiste Daroussin
1466d0ef721eSBaptiste Daroussin if ((fp = fopen(filename, "a")) == NULL)
1467d0ef721eSBaptiste Daroussin return errno;
1468d0ef721eSBaptiste Daroussin
1469d0ef721eSBaptiste Daroussin if (history(h, &ev, H_NSAVE_FP, (size_t)n, fp) == -1) {
1470d0ef721eSBaptiste Daroussin int serrno = errno ? errno : EINVAL;
1471d0ef721eSBaptiste Daroussin fclose(fp);
1472d0ef721eSBaptiste Daroussin return serrno;
1473d0ef721eSBaptiste Daroussin }
1474d0ef721eSBaptiste Daroussin fclose(fp);
1475d0ef721eSBaptiste Daroussin return 0;
1476d0ef721eSBaptiste Daroussin }
1477d0ef721eSBaptiste Daroussin
1478d0ef721eSBaptiste Daroussin /*
1479d0ef721eSBaptiste Daroussin * returns history ``num''th event
1480d0ef721eSBaptiste Daroussin *
1481d0ef721eSBaptiste Daroussin * returned pointer points to static variable
1482d0ef721eSBaptiste Daroussin */
1483d0ef721eSBaptiste Daroussin HIST_ENTRY *
history_get(int num)1484d0ef721eSBaptiste Daroussin history_get(int num)
1485d0ef721eSBaptiste Daroussin {
1486d0ef721eSBaptiste Daroussin static HIST_ENTRY she;
1487d0ef721eSBaptiste Daroussin HistEvent ev;
1488d0ef721eSBaptiste Daroussin int curr_num;
1489d0ef721eSBaptiste Daroussin
1490d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1491d0ef721eSBaptiste Daroussin rl_initialize();
1492d0ef721eSBaptiste Daroussin
1493d0ef721eSBaptiste Daroussin if (num < history_base)
1494d0ef721eSBaptiste Daroussin return NULL;
1495d0ef721eSBaptiste Daroussin
1496d0ef721eSBaptiste Daroussin /* save current position */
1497d0ef721eSBaptiste Daroussin if (history(h, &ev, H_CURR) != 0)
1498d0ef721eSBaptiste Daroussin return NULL;
1499d0ef721eSBaptiste Daroussin curr_num = ev.num;
1500d0ef721eSBaptiste Daroussin
1501d0ef721eSBaptiste Daroussin /*
1502d0ef721eSBaptiste Daroussin * use H_DELDATA to set to nth history (without delete) by passing
1503d0ef721eSBaptiste Daroussin * (void **)-1 -- as in history_set_pos
1504d0ef721eSBaptiste Daroussin */
1505d0ef721eSBaptiste Daroussin if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0)
1506d0ef721eSBaptiste Daroussin goto out;
1507d0ef721eSBaptiste Daroussin
1508d0ef721eSBaptiste Daroussin /* get current entry */
1509d0ef721eSBaptiste Daroussin if (history(h, &ev, H_CURR) != 0)
1510d0ef721eSBaptiste Daroussin goto out;
1511d0ef721eSBaptiste Daroussin if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0)
1512d0ef721eSBaptiste Daroussin goto out;
1513d0ef721eSBaptiste Daroussin she.line = ev.str;
1514d0ef721eSBaptiste Daroussin
1515d0ef721eSBaptiste Daroussin /* restore pointer to where it was */
1516d0ef721eSBaptiste Daroussin (void)history(h, &ev, H_SET, curr_num);
1517d0ef721eSBaptiste Daroussin
1518d0ef721eSBaptiste Daroussin return &she;
1519d0ef721eSBaptiste Daroussin
1520d0ef721eSBaptiste Daroussin out:
1521d0ef721eSBaptiste Daroussin /* restore pointer to where it was */
1522d0ef721eSBaptiste Daroussin (void)history(h, &ev, H_SET, curr_num);
1523d0ef721eSBaptiste Daroussin return NULL;
1524d0ef721eSBaptiste Daroussin }
1525d0ef721eSBaptiste Daroussin
1526d0ef721eSBaptiste Daroussin
1527d0ef721eSBaptiste Daroussin /*
1528d0ef721eSBaptiste Daroussin * add the line to history table
1529d0ef721eSBaptiste Daroussin */
1530d0ef721eSBaptiste Daroussin int
add_history(const char * line)1531d0ef721eSBaptiste Daroussin add_history(const char *line)
1532d0ef721eSBaptiste Daroussin {
1533d0ef721eSBaptiste Daroussin HistEvent ev;
1534d0ef721eSBaptiste Daroussin
1535d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1536d0ef721eSBaptiste Daroussin rl_initialize();
1537d0ef721eSBaptiste Daroussin
1538d0ef721eSBaptiste Daroussin if (history(h, &ev, H_ENTER, line) == -1)
1539d0ef721eSBaptiste Daroussin return 0;
1540d0ef721eSBaptiste Daroussin
1541d0ef721eSBaptiste Daroussin (void)history(h, &ev, H_GETSIZE);
1542d0ef721eSBaptiste Daroussin if (ev.num == history_length)
1543d0ef721eSBaptiste Daroussin history_base++;
1544d0ef721eSBaptiste Daroussin else {
1545d0ef721eSBaptiste Daroussin history_offset++;
1546d0ef721eSBaptiste Daroussin history_length = ev.num;
1547d0ef721eSBaptiste Daroussin }
1548d0ef721eSBaptiste Daroussin return 0;
1549d0ef721eSBaptiste Daroussin }
1550d0ef721eSBaptiste Daroussin
1551d0ef721eSBaptiste Daroussin
1552d0ef721eSBaptiste Daroussin /*
1553d0ef721eSBaptiste Daroussin * remove the specified entry from the history list and return it.
1554d0ef721eSBaptiste Daroussin */
1555d0ef721eSBaptiste Daroussin HIST_ENTRY *
remove_history(int num)1556d0ef721eSBaptiste Daroussin remove_history(int num)
1557d0ef721eSBaptiste Daroussin {
1558d0ef721eSBaptiste Daroussin HIST_ENTRY *he;
1559d0ef721eSBaptiste Daroussin HistEvent ev;
1560d0ef721eSBaptiste Daroussin
1561d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1562d0ef721eSBaptiste Daroussin rl_initialize();
1563d0ef721eSBaptiste Daroussin
1564d0ef721eSBaptiste Daroussin if ((he = el_malloc(sizeof(*he))) == NULL)
1565d0ef721eSBaptiste Daroussin return NULL;
1566d0ef721eSBaptiste Daroussin
1567d0ef721eSBaptiste Daroussin if (history(h, &ev, H_DELDATA, num, &he->data) != 0) {
1568d0ef721eSBaptiste Daroussin el_free(he);
1569d0ef721eSBaptiste Daroussin return NULL;
1570d0ef721eSBaptiste Daroussin }
1571d0ef721eSBaptiste Daroussin
1572d0ef721eSBaptiste Daroussin he->line = ev.str;
1573d0ef721eSBaptiste Daroussin if (history(h, &ev, H_GETSIZE) == 0)
1574d0ef721eSBaptiste Daroussin history_length = ev.num;
1575d0ef721eSBaptiste Daroussin
1576d0ef721eSBaptiste Daroussin return he;
1577d0ef721eSBaptiste Daroussin }
1578d0ef721eSBaptiste Daroussin
1579d0ef721eSBaptiste Daroussin
1580d0ef721eSBaptiste Daroussin /*
1581d0ef721eSBaptiste Daroussin * replace the line and data of the num-th entry
1582d0ef721eSBaptiste Daroussin */
1583d0ef721eSBaptiste Daroussin HIST_ENTRY *
replace_history_entry(int num,const char * line,histdata_t data)1584d0ef721eSBaptiste Daroussin replace_history_entry(int num, const char *line, histdata_t data)
1585d0ef721eSBaptiste Daroussin {
1586d0ef721eSBaptiste Daroussin HIST_ENTRY *he;
1587d0ef721eSBaptiste Daroussin HistEvent ev;
1588d0ef721eSBaptiste Daroussin int curr_num;
1589d0ef721eSBaptiste Daroussin
1590d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1591d0ef721eSBaptiste Daroussin rl_initialize();
1592d0ef721eSBaptiste Daroussin
1593d0ef721eSBaptiste Daroussin /* save current position */
1594d0ef721eSBaptiste Daroussin if (history(h, &ev, H_CURR) != 0)
1595d0ef721eSBaptiste Daroussin return NULL;
1596d0ef721eSBaptiste Daroussin curr_num = ev.num;
1597d0ef721eSBaptiste Daroussin
1598d0ef721eSBaptiste Daroussin /* start from the oldest */
1599d0ef721eSBaptiste Daroussin if (history(h, &ev, H_LAST) != 0)
1600d0ef721eSBaptiste Daroussin return NULL; /* error */
1601d0ef721eSBaptiste Daroussin
1602d0ef721eSBaptiste Daroussin if ((he = el_malloc(sizeof(*he))) == NULL)
1603d0ef721eSBaptiste Daroussin return NULL;
1604d0ef721eSBaptiste Daroussin
1605d0ef721eSBaptiste Daroussin /* look forwards for event matching specified offset */
1606d0ef721eSBaptiste Daroussin if (history(h, &ev, H_NEXT_EVDATA, num, &he->data))
1607d0ef721eSBaptiste Daroussin goto out;
1608d0ef721eSBaptiste Daroussin
1609*baff8195SBaptiste Daroussin he->line = ev.str;
1610d0ef721eSBaptiste Daroussin if (he->line == NULL)
1611d0ef721eSBaptiste Daroussin goto out;
1612d0ef721eSBaptiste Daroussin
1613d0ef721eSBaptiste Daroussin if (history(h, &ev, H_REPLACE, line, data))
1614d0ef721eSBaptiste Daroussin goto out;
1615d0ef721eSBaptiste Daroussin
1616d0ef721eSBaptiste Daroussin /* restore pointer to where it was */
1617d0ef721eSBaptiste Daroussin if (history(h, &ev, H_SET, curr_num))
1618d0ef721eSBaptiste Daroussin goto out;
1619d0ef721eSBaptiste Daroussin
1620d0ef721eSBaptiste Daroussin return he;
1621d0ef721eSBaptiste Daroussin out:
1622d0ef721eSBaptiste Daroussin el_free(he);
1623d0ef721eSBaptiste Daroussin return NULL;
1624d0ef721eSBaptiste Daroussin }
1625d0ef721eSBaptiste Daroussin
1626d0ef721eSBaptiste Daroussin /*
1627d0ef721eSBaptiste Daroussin * clear the history list - delete all entries
1628d0ef721eSBaptiste Daroussin */
1629d0ef721eSBaptiste Daroussin void
clear_history(void)1630d0ef721eSBaptiste Daroussin clear_history(void)
1631d0ef721eSBaptiste Daroussin {
1632d0ef721eSBaptiste Daroussin HistEvent ev;
1633d0ef721eSBaptiste Daroussin
1634d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1635d0ef721eSBaptiste Daroussin rl_initialize();
1636d0ef721eSBaptiste Daroussin
1637d0ef721eSBaptiste Daroussin (void)history(h, &ev, H_CLEAR);
1638d0ef721eSBaptiste Daroussin history_offset = history_length = 0;
1639d0ef721eSBaptiste Daroussin }
1640d0ef721eSBaptiste Daroussin
1641d0ef721eSBaptiste Daroussin
1642d0ef721eSBaptiste Daroussin /*
1643d0ef721eSBaptiste Daroussin * returns offset of the current history event
1644d0ef721eSBaptiste Daroussin */
1645d0ef721eSBaptiste Daroussin int
where_history(void)1646d0ef721eSBaptiste Daroussin where_history(void)
1647d0ef721eSBaptiste Daroussin {
1648d0ef721eSBaptiste Daroussin return history_offset;
1649d0ef721eSBaptiste Daroussin }
1650d0ef721eSBaptiste Daroussin
1651d0ef721eSBaptiste Daroussin static HIST_ENTRY **_history_listp;
1652d0ef721eSBaptiste Daroussin static HIST_ENTRY *_history_list;
1653d0ef721eSBaptiste Daroussin
1654d0ef721eSBaptiste Daroussin HIST_ENTRY **
history_list(void)1655d0ef721eSBaptiste Daroussin history_list(void)
1656d0ef721eSBaptiste Daroussin {
1657d0ef721eSBaptiste Daroussin HistEvent ev;
1658d0ef721eSBaptiste Daroussin HIST_ENTRY **nlp, *nl;
1659d0ef721eSBaptiste Daroussin int i;
1660d0ef721eSBaptiste Daroussin
1661d0ef721eSBaptiste Daroussin if (history(h, &ev, H_LAST) != 0)
1662d0ef721eSBaptiste Daroussin return NULL;
1663d0ef721eSBaptiste Daroussin
1664d0ef721eSBaptiste Daroussin if ((nlp = el_realloc(_history_listp,
1665d0ef721eSBaptiste Daroussin ((size_t)history_length + 1) * sizeof(*nlp))) == NULL)
1666d0ef721eSBaptiste Daroussin return NULL;
1667d0ef721eSBaptiste Daroussin _history_listp = nlp;
1668d0ef721eSBaptiste Daroussin
1669d0ef721eSBaptiste Daroussin if ((nl = el_realloc(_history_list,
1670d0ef721eSBaptiste Daroussin (size_t)history_length * sizeof(*nl))) == NULL)
1671d0ef721eSBaptiste Daroussin return NULL;
1672d0ef721eSBaptiste Daroussin _history_list = nl;
1673d0ef721eSBaptiste Daroussin
1674d0ef721eSBaptiste Daroussin i = 0;
1675d0ef721eSBaptiste Daroussin do {
1676d0ef721eSBaptiste Daroussin _history_listp[i] = &_history_list[i];
1677d0ef721eSBaptiste Daroussin _history_list[i].line = ev.str;
1678d0ef721eSBaptiste Daroussin _history_list[i].data = NULL;
1679d0ef721eSBaptiste Daroussin if (i++ == history_length)
1680d0ef721eSBaptiste Daroussin abort();
1681d0ef721eSBaptiste Daroussin } while (history(h, &ev, H_PREV) == 0);
1682d0ef721eSBaptiste Daroussin _history_listp[i] = NULL;
1683d0ef721eSBaptiste Daroussin return _history_listp;
1684d0ef721eSBaptiste Daroussin }
1685d0ef721eSBaptiste Daroussin
1686d0ef721eSBaptiste Daroussin /*
1687d0ef721eSBaptiste Daroussin * returns current history event or NULL if there is no such event
1688d0ef721eSBaptiste Daroussin */
1689d0ef721eSBaptiste Daroussin HIST_ENTRY *
current_history(void)1690d0ef721eSBaptiste Daroussin current_history(void)
1691d0ef721eSBaptiste Daroussin {
1692d0ef721eSBaptiste Daroussin HistEvent ev;
1693d0ef721eSBaptiste Daroussin
1694d0ef721eSBaptiste Daroussin if (history(h, &ev, H_PREV_EVENT, history_offset + 1) != 0)
1695d0ef721eSBaptiste Daroussin return NULL;
1696d0ef721eSBaptiste Daroussin
1697d0ef721eSBaptiste Daroussin rl_he.line = ev.str;
1698d0ef721eSBaptiste Daroussin rl_he.data = NULL;
1699d0ef721eSBaptiste Daroussin return &rl_he;
1700d0ef721eSBaptiste Daroussin }
1701d0ef721eSBaptiste Daroussin
1702d0ef721eSBaptiste Daroussin
1703d0ef721eSBaptiste Daroussin /*
1704d0ef721eSBaptiste Daroussin * returns total number of bytes history events' data are using
1705d0ef721eSBaptiste Daroussin */
1706d0ef721eSBaptiste Daroussin int
history_total_bytes(void)1707d0ef721eSBaptiste Daroussin history_total_bytes(void)
1708d0ef721eSBaptiste Daroussin {
1709d0ef721eSBaptiste Daroussin HistEvent ev;
1710d0ef721eSBaptiste Daroussin int curr_num;
1711d0ef721eSBaptiste Daroussin size_t size;
1712d0ef721eSBaptiste Daroussin
1713d0ef721eSBaptiste Daroussin if (history(h, &ev, H_CURR) != 0)
1714d0ef721eSBaptiste Daroussin return -1;
1715d0ef721eSBaptiste Daroussin curr_num = ev.num;
1716d0ef721eSBaptiste Daroussin
1717d0ef721eSBaptiste Daroussin (void)history(h, &ev, H_FIRST);
1718d0ef721eSBaptiste Daroussin size = 0;
1719d0ef721eSBaptiste Daroussin do
1720d0ef721eSBaptiste Daroussin size += strlen(ev.str) * sizeof(*ev.str);
1721d0ef721eSBaptiste Daroussin while (history(h, &ev, H_NEXT) == 0);
1722d0ef721eSBaptiste Daroussin
1723d0ef721eSBaptiste Daroussin /* get to the same position as before */
1724d0ef721eSBaptiste Daroussin history(h, &ev, H_PREV_EVENT, curr_num);
1725d0ef721eSBaptiste Daroussin
1726d0ef721eSBaptiste Daroussin return (int)size;
1727d0ef721eSBaptiste Daroussin }
1728d0ef721eSBaptiste Daroussin
1729d0ef721eSBaptiste Daroussin
1730d0ef721eSBaptiste Daroussin /*
1731d0ef721eSBaptiste Daroussin * sets the position in the history list to ``pos''
1732d0ef721eSBaptiste Daroussin */
1733d0ef721eSBaptiste Daroussin int
history_set_pos(int pos)1734d0ef721eSBaptiste Daroussin history_set_pos(int pos)
1735d0ef721eSBaptiste Daroussin {
1736d0ef721eSBaptiste Daroussin if (pos >= history_length || pos < 0)
1737d0ef721eSBaptiste Daroussin return 0;
1738d0ef721eSBaptiste Daroussin
1739d0ef721eSBaptiste Daroussin history_offset = pos;
1740d0ef721eSBaptiste Daroussin return 1;
1741d0ef721eSBaptiste Daroussin }
1742d0ef721eSBaptiste Daroussin
1743d0ef721eSBaptiste Daroussin
1744d0ef721eSBaptiste Daroussin /*
1745d0ef721eSBaptiste Daroussin * returns previous event in history and shifts pointer accordingly
1746d0ef721eSBaptiste Daroussin * Note that readline and editline define directions in opposite ways.
1747d0ef721eSBaptiste Daroussin */
1748d0ef721eSBaptiste Daroussin HIST_ENTRY *
previous_history(void)1749d0ef721eSBaptiste Daroussin previous_history(void)
1750d0ef721eSBaptiste Daroussin {
1751d0ef721eSBaptiste Daroussin HistEvent ev;
1752d0ef721eSBaptiste Daroussin
1753d0ef721eSBaptiste Daroussin if (history_offset == 0)
1754d0ef721eSBaptiste Daroussin return NULL;
1755d0ef721eSBaptiste Daroussin
1756d0ef721eSBaptiste Daroussin if (history(h, &ev, H_LAST) != 0)
1757d0ef721eSBaptiste Daroussin return NULL;
1758d0ef721eSBaptiste Daroussin
1759d0ef721eSBaptiste Daroussin history_offset--;
1760d0ef721eSBaptiste Daroussin return current_history();
1761d0ef721eSBaptiste Daroussin }
1762d0ef721eSBaptiste Daroussin
1763d0ef721eSBaptiste Daroussin
1764d0ef721eSBaptiste Daroussin /*
1765d0ef721eSBaptiste Daroussin * returns next event in history and shifts pointer accordingly
1766d0ef721eSBaptiste Daroussin */
1767d0ef721eSBaptiste Daroussin HIST_ENTRY *
next_history(void)1768d0ef721eSBaptiste Daroussin next_history(void)
1769d0ef721eSBaptiste Daroussin {
1770d0ef721eSBaptiste Daroussin HistEvent ev;
1771d0ef721eSBaptiste Daroussin
1772d0ef721eSBaptiste Daroussin if (history_offset >= history_length)
1773d0ef721eSBaptiste Daroussin return NULL;
1774d0ef721eSBaptiste Daroussin
1775d0ef721eSBaptiste Daroussin if (history(h, &ev, H_LAST) != 0)
1776d0ef721eSBaptiste Daroussin return NULL;
1777d0ef721eSBaptiste Daroussin
1778d0ef721eSBaptiste Daroussin history_offset++;
1779d0ef721eSBaptiste Daroussin return current_history();
1780d0ef721eSBaptiste Daroussin }
1781d0ef721eSBaptiste Daroussin
1782d0ef721eSBaptiste Daroussin
1783d0ef721eSBaptiste Daroussin /*
1784d0ef721eSBaptiste Daroussin * searches for first history event containing the str
1785d0ef721eSBaptiste Daroussin */
1786d0ef721eSBaptiste Daroussin int
history_search(const char * str,int direction)1787d0ef721eSBaptiste Daroussin history_search(const char *str, int direction)
1788d0ef721eSBaptiste Daroussin {
1789d0ef721eSBaptiste Daroussin HistEvent ev;
1790d0ef721eSBaptiste Daroussin const char *strp;
1791d0ef721eSBaptiste Daroussin int curr_num;
1792d0ef721eSBaptiste Daroussin
1793d0ef721eSBaptiste Daroussin if (history(h, &ev, H_CURR) != 0)
1794d0ef721eSBaptiste Daroussin return -1;
1795d0ef721eSBaptiste Daroussin curr_num = ev.num;
1796d0ef721eSBaptiste Daroussin
1797d0ef721eSBaptiste Daroussin for (;;) {
1798d0ef721eSBaptiste Daroussin if ((strp = strstr(ev.str, str)) != NULL)
1799d0ef721eSBaptiste Daroussin return (int)(strp - ev.str);
1800d0ef721eSBaptiste Daroussin if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
1801d0ef721eSBaptiste Daroussin break;
1802d0ef721eSBaptiste Daroussin }
1803d0ef721eSBaptiste Daroussin (void)history(h, &ev, H_SET, curr_num);
1804d0ef721eSBaptiste Daroussin return -1;
1805d0ef721eSBaptiste Daroussin }
1806d0ef721eSBaptiste Daroussin
1807d0ef721eSBaptiste Daroussin
1808d0ef721eSBaptiste Daroussin /*
1809d0ef721eSBaptiste Daroussin * searches for first history event beginning with str
1810d0ef721eSBaptiste Daroussin */
1811d0ef721eSBaptiste Daroussin int
history_search_prefix(const char * str,int direction)1812d0ef721eSBaptiste Daroussin history_search_prefix(const char *str, int direction)
1813d0ef721eSBaptiste Daroussin {
1814d0ef721eSBaptiste Daroussin HistEvent ev;
1815d0ef721eSBaptiste Daroussin
1816d0ef721eSBaptiste Daroussin return (history(h, &ev, direction < 0 ?
1817d0ef721eSBaptiste Daroussin H_PREV_STR : H_NEXT_STR, str));
1818d0ef721eSBaptiste Daroussin }
1819d0ef721eSBaptiste Daroussin
1820d0ef721eSBaptiste Daroussin
1821d0ef721eSBaptiste Daroussin /*
1822d0ef721eSBaptiste Daroussin * search for event in history containing str, starting at offset
1823d0ef721eSBaptiste Daroussin * abs(pos); continue backward, if pos<0, forward otherwise
1824d0ef721eSBaptiste Daroussin */
1825d0ef721eSBaptiste Daroussin /* ARGSUSED */
1826d0ef721eSBaptiste Daroussin int
history_search_pos(const char * str,int direction,int pos)1827d0ef721eSBaptiste Daroussin history_search_pos(const char *str,
1828d0ef721eSBaptiste Daroussin int direction __attribute__((__unused__)), int pos)
1829d0ef721eSBaptiste Daroussin {
1830d0ef721eSBaptiste Daroussin HistEvent ev;
1831d0ef721eSBaptiste Daroussin int curr_num, off;
1832d0ef721eSBaptiste Daroussin
1833d0ef721eSBaptiste Daroussin off = (pos > 0) ? pos : -pos;
1834d0ef721eSBaptiste Daroussin pos = (pos > 0) ? 1 : -1;
1835d0ef721eSBaptiste Daroussin
1836d0ef721eSBaptiste Daroussin if (history(h, &ev, H_CURR) != 0)
1837d0ef721eSBaptiste Daroussin return -1;
1838d0ef721eSBaptiste Daroussin curr_num = ev.num;
1839d0ef721eSBaptiste Daroussin
1840d0ef721eSBaptiste Daroussin if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0)
1841d0ef721eSBaptiste Daroussin return -1;
1842d0ef721eSBaptiste Daroussin
1843d0ef721eSBaptiste Daroussin for (;;) {
1844d0ef721eSBaptiste Daroussin if (strstr(ev.str, str))
1845d0ef721eSBaptiste Daroussin return off;
1846d0ef721eSBaptiste Daroussin if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
1847d0ef721eSBaptiste Daroussin break;
1848d0ef721eSBaptiste Daroussin }
1849d0ef721eSBaptiste Daroussin
1850d0ef721eSBaptiste Daroussin /* set "current" pointer back to previous state */
1851d0ef721eSBaptiste Daroussin (void)history(h, &ev,
1852d0ef721eSBaptiste Daroussin pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
1853d0ef721eSBaptiste Daroussin
1854d0ef721eSBaptiste Daroussin return -1;
1855d0ef721eSBaptiste Daroussin }
1856d0ef721eSBaptiste Daroussin
1857d0ef721eSBaptiste Daroussin
1858d0ef721eSBaptiste Daroussin /********************************/
1859d0ef721eSBaptiste Daroussin /* completion functions */
1860d0ef721eSBaptiste Daroussin
1861d0ef721eSBaptiste Daroussin char *
tilde_expand(char * name)1862d0ef721eSBaptiste Daroussin tilde_expand(char *name)
1863d0ef721eSBaptiste Daroussin {
1864d0ef721eSBaptiste Daroussin return fn_tilde_expand(name);
1865d0ef721eSBaptiste Daroussin }
1866d0ef721eSBaptiste Daroussin
1867d0ef721eSBaptiste Daroussin char *
filename_completion_function(const char * name,int state)1868d0ef721eSBaptiste Daroussin filename_completion_function(const char *name, int state)
1869d0ef721eSBaptiste Daroussin {
1870d0ef721eSBaptiste Daroussin return fn_filename_completion_function(name, state);
1871d0ef721eSBaptiste Daroussin }
1872d0ef721eSBaptiste Daroussin
1873d0ef721eSBaptiste Daroussin /*
1874d0ef721eSBaptiste Daroussin * a completion generator for usernames; returns _first_ username
1875d0ef721eSBaptiste Daroussin * which starts with supplied text
1876d0ef721eSBaptiste Daroussin * text contains a partial username preceded by random character
1877d0ef721eSBaptiste Daroussin * (usually '~'); state resets search from start (??? should we do that anyway)
1878d0ef721eSBaptiste Daroussin * it's the caller's responsibility to free the returned value
1879d0ef721eSBaptiste Daroussin */
1880d0ef721eSBaptiste Daroussin char *
username_completion_function(const char * text,int state)1881d0ef721eSBaptiste Daroussin username_completion_function(const char *text, int state)
1882d0ef721eSBaptiste Daroussin {
1883d0ef721eSBaptiste Daroussin #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1884d0ef721eSBaptiste Daroussin struct passwd pwres;
1885d0ef721eSBaptiste Daroussin char pwbuf[1024];
1886d0ef721eSBaptiste Daroussin #endif
1887d0ef721eSBaptiste Daroussin struct passwd *pass = NULL;
1888d0ef721eSBaptiste Daroussin
1889d0ef721eSBaptiste Daroussin if (text[0] == '\0')
1890d0ef721eSBaptiste Daroussin return NULL;
1891d0ef721eSBaptiste Daroussin
1892d0ef721eSBaptiste Daroussin if (*text == '~')
1893d0ef721eSBaptiste Daroussin text++;
1894d0ef721eSBaptiste Daroussin
1895d0ef721eSBaptiste Daroussin if (state == 0)
1896d0ef721eSBaptiste Daroussin setpwent();
1897d0ef721eSBaptiste Daroussin
1898d0ef721eSBaptiste Daroussin while (
1899d0ef721eSBaptiste Daroussin #if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1900d0ef721eSBaptiste Daroussin getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL
1901d0ef721eSBaptiste Daroussin #else
1902d0ef721eSBaptiste Daroussin (pass = getpwent()) != NULL
1903d0ef721eSBaptiste Daroussin #endif
1904d0ef721eSBaptiste Daroussin && text[0] == pass->pw_name[0]
1905d0ef721eSBaptiste Daroussin && strcmp(text, pass->pw_name) == 0)
1906d0ef721eSBaptiste Daroussin continue;
1907d0ef721eSBaptiste Daroussin
1908d0ef721eSBaptiste Daroussin if (pass == NULL) {
1909d0ef721eSBaptiste Daroussin endpwent();
1910d0ef721eSBaptiste Daroussin return NULL;
1911d0ef721eSBaptiste Daroussin }
1912d0ef721eSBaptiste Daroussin return strdup(pass->pw_name);
1913d0ef721eSBaptiste Daroussin }
1914d0ef721eSBaptiste Daroussin
1915d0ef721eSBaptiste Daroussin
1916d0ef721eSBaptiste Daroussin /*
1917d0ef721eSBaptiste Daroussin * el-compatible wrapper to send TSTP on ^Z
1918d0ef721eSBaptiste Daroussin */
1919d0ef721eSBaptiste Daroussin /* ARGSUSED */
1920d0ef721eSBaptiste Daroussin static unsigned char
_el_rl_tstp(EditLine * el,int ch)1921d0ef721eSBaptiste Daroussin _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
1922d0ef721eSBaptiste Daroussin {
1923d0ef721eSBaptiste Daroussin (void)kill(0, SIGTSTP);
1924d0ef721eSBaptiste Daroussin return CC_NORM;
1925d0ef721eSBaptiste Daroussin }
1926d0ef721eSBaptiste Daroussin
1927d0ef721eSBaptiste Daroussin static const char *
1928d0ef721eSBaptiste Daroussin /*ARGSUSED*/
_rl_completion_append_character_function(const char * dummy)1929d0ef721eSBaptiste Daroussin _rl_completion_append_character_function(const char *dummy
1930d0ef721eSBaptiste Daroussin __attribute__((__unused__)))
1931d0ef721eSBaptiste Daroussin {
1932d0ef721eSBaptiste Daroussin static char buf[2];
1933d0ef721eSBaptiste Daroussin buf[0] = (char)rl_completion_append_character;
1934d0ef721eSBaptiste Daroussin buf[1] = '\0';
1935d0ef721eSBaptiste Daroussin return buf;
1936d0ef721eSBaptiste Daroussin }
1937d0ef721eSBaptiste Daroussin
1938d0ef721eSBaptiste Daroussin
1939d0ef721eSBaptiste Daroussin /*
1940d0ef721eSBaptiste Daroussin * Display list of strings in columnar format on readline's output stream.
1941d0ef721eSBaptiste Daroussin * 'matches' is list of strings, 'len' is number of strings in 'matches',
1942d0ef721eSBaptiste Daroussin * 'max' is maximum length of string in 'matches'.
1943d0ef721eSBaptiste Daroussin */
1944d0ef721eSBaptiste Daroussin void
rl_display_match_list(char ** matches,int len,int max)1945d0ef721eSBaptiste Daroussin rl_display_match_list(char **matches, int len, int max)
1946d0ef721eSBaptiste Daroussin {
1947d0ef721eSBaptiste Daroussin
1948d0ef721eSBaptiste Daroussin fn_display_match_list(e, matches, (size_t)len, (size_t)max,
1949d0ef721eSBaptiste Daroussin _rl_completion_append_character_function);
1950d0ef721eSBaptiste Daroussin }
1951d0ef721eSBaptiste Daroussin
1952d0ef721eSBaptiste Daroussin /*
1953d0ef721eSBaptiste Daroussin * complete word at current point
1954d0ef721eSBaptiste Daroussin */
1955d0ef721eSBaptiste Daroussin /* ARGSUSED */
1956d0ef721eSBaptiste Daroussin int
rl_complete(int ignore,int invoking_key)1957d0ef721eSBaptiste Daroussin rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
1958d0ef721eSBaptiste Daroussin {
1959d0ef721eSBaptiste Daroussin static ct_buffer_t wbreak_conv, sprefix_conv;
1960d0ef721eSBaptiste Daroussin const char *breakchars;
1961d0ef721eSBaptiste Daroussin
1962d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
1963d0ef721eSBaptiste Daroussin rl_initialize();
1964d0ef721eSBaptiste Daroussin
1965d0ef721eSBaptiste Daroussin if (rl_inhibit_completion) {
1966d0ef721eSBaptiste Daroussin char arr[2];
1967d0ef721eSBaptiste Daroussin arr[0] = (char)invoking_key;
1968d0ef721eSBaptiste Daroussin arr[1] = '\0';
1969d0ef721eSBaptiste Daroussin el_insertstr(e, arr);
1970d0ef721eSBaptiste Daroussin return CC_REFRESH;
1971d0ef721eSBaptiste Daroussin }
1972d0ef721eSBaptiste Daroussin
1973d0ef721eSBaptiste Daroussin if (rl_completion_word_break_hook != NULL)
1974d0ef721eSBaptiste Daroussin breakchars = (*rl_completion_word_break_hook)();
1975d0ef721eSBaptiste Daroussin else
1976d0ef721eSBaptiste Daroussin breakchars = rl_basic_word_break_characters;
1977d0ef721eSBaptiste Daroussin
1978d0ef721eSBaptiste Daroussin _rl_update_pos();
1979d0ef721eSBaptiste Daroussin
1980d0ef721eSBaptiste Daroussin /* Just look at how many global variables modify this operation! */
1981d0ef721eSBaptiste Daroussin return fn_complete(e,
1982d0ef721eSBaptiste Daroussin (rl_compentry_func_t *)rl_completion_entry_function,
1983d0ef721eSBaptiste Daroussin rl_attempted_completion_function,
1984d0ef721eSBaptiste Daroussin ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
1985d0ef721eSBaptiste Daroussin ct_decode_string(breakchars, &sprefix_conv),
1986d0ef721eSBaptiste Daroussin _rl_completion_append_character_function,
1987d0ef721eSBaptiste Daroussin (size_t)rl_completion_query_items,
1988d0ef721eSBaptiste Daroussin &rl_completion_type, &rl_attempted_completion_over,
1989d0ef721eSBaptiste Daroussin &rl_point, &rl_end);
1990d0ef721eSBaptiste Daroussin
1991d0ef721eSBaptiste Daroussin
1992d0ef721eSBaptiste Daroussin }
1993d0ef721eSBaptiste Daroussin
1994d0ef721eSBaptiste Daroussin
1995d0ef721eSBaptiste Daroussin /* ARGSUSED */
1996d0ef721eSBaptiste Daroussin static unsigned char
_el_rl_complete(EditLine * el,int ch)1997d0ef721eSBaptiste Daroussin _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
1998d0ef721eSBaptiste Daroussin {
1999d0ef721eSBaptiste Daroussin return (unsigned char)rl_complete(0, ch);
2000d0ef721eSBaptiste Daroussin }
2001d0ef721eSBaptiste Daroussin
2002d0ef721eSBaptiste Daroussin /*
2003d0ef721eSBaptiste Daroussin * misc other functions
2004d0ef721eSBaptiste Daroussin */
2005d0ef721eSBaptiste Daroussin
2006d0ef721eSBaptiste Daroussin /*
2007d0ef721eSBaptiste Daroussin * bind key c to readline-type function func
2008d0ef721eSBaptiste Daroussin */
2009d0ef721eSBaptiste Daroussin int
rl_bind_key(int c,rl_command_func_t * func)2010d0ef721eSBaptiste Daroussin rl_bind_key(int c, rl_command_func_t *func)
2011d0ef721eSBaptiste Daroussin {
2012d0ef721eSBaptiste Daroussin int retval = -1;
2013d0ef721eSBaptiste Daroussin
2014d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
2015d0ef721eSBaptiste Daroussin rl_initialize();
2016d0ef721eSBaptiste Daroussin
2017d0ef721eSBaptiste Daroussin if (func == rl_insert) {
2018d0ef721eSBaptiste Daroussin /* XXX notice there is no range checking of ``c'' */
2019d0ef721eSBaptiste Daroussin e->el_map.key[c] = ED_INSERT;
2020d0ef721eSBaptiste Daroussin retval = 0;
2021d0ef721eSBaptiste Daroussin }
2022d0ef721eSBaptiste Daroussin return retval;
2023d0ef721eSBaptiste Daroussin }
2024d0ef721eSBaptiste Daroussin
2025d0ef721eSBaptiste Daroussin
2026d0ef721eSBaptiste Daroussin /*
2027d0ef721eSBaptiste Daroussin * read one key from input - handles chars pushed back
2028d0ef721eSBaptiste Daroussin * to input stream also
2029d0ef721eSBaptiste Daroussin */
2030d0ef721eSBaptiste Daroussin int
rl_read_key(void)2031d0ef721eSBaptiste Daroussin rl_read_key(void)
2032d0ef721eSBaptiste Daroussin {
2033d0ef721eSBaptiste Daroussin char fooarr[2 * sizeof(int)];
2034d0ef721eSBaptiste Daroussin
2035d0ef721eSBaptiste Daroussin if (e == NULL || h == NULL)
2036d0ef721eSBaptiste Daroussin rl_initialize();
2037d0ef721eSBaptiste Daroussin
2038d0ef721eSBaptiste Daroussin return el_getc(e, fooarr);
2039d0ef721eSBaptiste Daroussin }
2040d0ef721eSBaptiste Daroussin
2041d0ef721eSBaptiste Daroussin
2042d0ef721eSBaptiste Daroussin /*
2043d0ef721eSBaptiste Daroussin * reset the terminal
2044d0ef721eSBaptiste Daroussin */
2045d0ef721eSBaptiste Daroussin /* ARGSUSED */
2046d0ef721eSBaptiste Daroussin int
rl_reset_terminal(const char * p)2047d0ef721eSBaptiste Daroussin rl_reset_terminal(const char *p __attribute__((__unused__)))
2048d0ef721eSBaptiste Daroussin {
2049d0ef721eSBaptiste Daroussin
2050d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
2051d0ef721eSBaptiste Daroussin rl_initialize();
2052d0ef721eSBaptiste Daroussin el_reset(e);
2053d0ef721eSBaptiste Daroussin return 0;
2054d0ef721eSBaptiste Daroussin }
2055d0ef721eSBaptiste Daroussin
2056d0ef721eSBaptiste Daroussin
2057d0ef721eSBaptiste Daroussin /*
2058d0ef721eSBaptiste Daroussin * insert character ``c'' back into input stream, ``count'' times
2059d0ef721eSBaptiste Daroussin */
2060d0ef721eSBaptiste Daroussin int
rl_insert(int count,int c)2061d0ef721eSBaptiste Daroussin rl_insert(int count, int c)
2062d0ef721eSBaptiste Daroussin {
2063d0ef721eSBaptiste Daroussin char arr[2];
2064d0ef721eSBaptiste Daroussin
2065d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
2066d0ef721eSBaptiste Daroussin rl_initialize();
2067d0ef721eSBaptiste Daroussin
2068d0ef721eSBaptiste Daroussin /* XXX - int -> char conversion can lose on multichars */
2069d0ef721eSBaptiste Daroussin arr[0] = (char)c;
2070d0ef721eSBaptiste Daroussin arr[1] = '\0';
2071d0ef721eSBaptiste Daroussin
2072d0ef721eSBaptiste Daroussin for (; count > 0; count--)
2073d0ef721eSBaptiste Daroussin el_push(e, arr);
2074d0ef721eSBaptiste Daroussin
2075d0ef721eSBaptiste Daroussin return 0;
2076d0ef721eSBaptiste Daroussin }
2077d0ef721eSBaptiste Daroussin
2078d0ef721eSBaptiste Daroussin int
rl_insert_text(const char * text)2079d0ef721eSBaptiste Daroussin rl_insert_text(const char *text)
2080d0ef721eSBaptiste Daroussin {
2081d0ef721eSBaptiste Daroussin if (!text || *text == 0)
2082d0ef721eSBaptiste Daroussin return 0;
2083d0ef721eSBaptiste Daroussin
2084d0ef721eSBaptiste Daroussin if (h == NULL || e == NULL)
2085d0ef721eSBaptiste Daroussin rl_initialize();
2086d0ef721eSBaptiste Daroussin
2087d0ef721eSBaptiste Daroussin if (el_insertstr(e, text) < 0)
2088d0ef721eSBaptiste Daroussin return 0;
2089d0ef721eSBaptiste Daroussin return (int)strlen(text);
2090d0ef721eSBaptiste Daroussin }
2091d0ef721eSBaptiste Daroussin
2092d0ef721eSBaptiste Daroussin /*ARGSUSED*/
2093d0ef721eSBaptiste Daroussin int
rl_newline(int count,int c)2094d0ef721eSBaptiste Daroussin rl_newline(int count __attribute__((__unused__)),
2095d0ef721eSBaptiste Daroussin int c __attribute__((__unused__)))
2096d0ef721eSBaptiste Daroussin {
2097d0ef721eSBaptiste Daroussin /*
2098d0ef721eSBaptiste Daroussin * Readline-4.0 appears to ignore the args.
2099d0ef721eSBaptiste Daroussin */
2100d0ef721eSBaptiste Daroussin return rl_insert(1, '\n');
2101d0ef721eSBaptiste Daroussin }
2102d0ef721eSBaptiste Daroussin
2103d0ef721eSBaptiste Daroussin /*ARGSUSED*/
2104d0ef721eSBaptiste Daroussin static unsigned char
rl_bind_wrapper(EditLine * el,unsigned char c)2105d0ef721eSBaptiste Daroussin rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c)
2106d0ef721eSBaptiste Daroussin {
2107d0ef721eSBaptiste Daroussin if (map[c] == NULL)
2108d0ef721eSBaptiste Daroussin return CC_ERROR;
2109d0ef721eSBaptiste Daroussin
2110d0ef721eSBaptiste Daroussin _rl_update_pos();
2111d0ef721eSBaptiste Daroussin
2112d0ef721eSBaptiste Daroussin (*map[c])(1, c);
2113d0ef721eSBaptiste Daroussin
2114d0ef721eSBaptiste Daroussin /* If rl_done was set by the above call, deal with it here */
2115d0ef721eSBaptiste Daroussin if (rl_done)
2116d0ef721eSBaptiste Daroussin return CC_EOF;
2117d0ef721eSBaptiste Daroussin
2118d0ef721eSBaptiste Daroussin return CC_NORM;
2119d0ef721eSBaptiste Daroussin }
2120d0ef721eSBaptiste Daroussin
2121d0ef721eSBaptiste Daroussin int
rl_add_defun(const char * name,rl_command_func_t * fun,int c)2122d0ef721eSBaptiste Daroussin rl_add_defun(const char *name, rl_command_func_t *fun, int c)
2123d0ef721eSBaptiste Daroussin {
2124d0ef721eSBaptiste Daroussin char dest[8];
2125d0ef721eSBaptiste Daroussin if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
2126d0ef721eSBaptiste Daroussin return -1;
2127d0ef721eSBaptiste Daroussin map[(unsigned char)c] = fun;
2128d0ef721eSBaptiste Daroussin el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
2129d0ef721eSBaptiste Daroussin vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
2130d0ef721eSBaptiste Daroussin el_set(e, EL_BIND, dest, name, NULL);
2131d0ef721eSBaptiste Daroussin return 0;
2132d0ef721eSBaptiste Daroussin }
2133d0ef721eSBaptiste Daroussin
2134d0ef721eSBaptiste Daroussin void
rl_callback_read_char(void)2135d0ef721eSBaptiste Daroussin rl_callback_read_char(void)
2136d0ef721eSBaptiste Daroussin {
2137d0ef721eSBaptiste Daroussin int count = 0, done = 0;
2138d0ef721eSBaptiste Daroussin const char *buf = el_gets(e, &count);
2139d0ef721eSBaptiste Daroussin char *wbuf;
2140d0ef721eSBaptiste Daroussin
214191f76417SBaptiste Daroussin el_set(e, EL_UNBUFFERED, 1);
2142d0ef721eSBaptiste Daroussin if (buf == NULL || count-- <= 0)
2143d0ef721eSBaptiste Daroussin return;
2144d0ef721eSBaptiste Daroussin if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
2145d0ef721eSBaptiste Daroussin done = 1;
2146d0ef721eSBaptiste Daroussin if (buf[count] == '\n' || buf[count] == '\r')
2147d0ef721eSBaptiste Daroussin done = 2;
2148d0ef721eSBaptiste Daroussin
2149d0ef721eSBaptiste Daroussin if (done && rl_linefunc != NULL) {
2150d0ef721eSBaptiste Daroussin el_set(e, EL_UNBUFFERED, 0);
2151d0ef721eSBaptiste Daroussin if (done == 2) {
2152d0ef721eSBaptiste Daroussin if ((wbuf = strdup(buf)) != NULL)
2153d0ef721eSBaptiste Daroussin wbuf[count] = '\0';
21547f399375SBaptiste Daroussin RL_SETSTATE(RL_STATE_DONE);
2155d0ef721eSBaptiste Daroussin } else
2156d0ef721eSBaptiste Daroussin wbuf = NULL;
2157d0ef721eSBaptiste Daroussin (*(void (*)(const char *))rl_linefunc)(wbuf);
2158d0ef721eSBaptiste Daroussin }
21597f399375SBaptiste Daroussin _rl_update_pos();
2160d0ef721eSBaptiste Daroussin }
2161d0ef721eSBaptiste Daroussin
2162d0ef721eSBaptiste Daroussin void
rl_callback_handler_install(const char * prompt,rl_vcpfunc_t * linefunc)2163d0ef721eSBaptiste Daroussin rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc)
2164d0ef721eSBaptiste Daroussin {
2165d0ef721eSBaptiste Daroussin if (e == NULL) {
2166d0ef721eSBaptiste Daroussin rl_initialize();
2167d0ef721eSBaptiste Daroussin }
2168d0ef721eSBaptiste Daroussin (void)rl_set_prompt(prompt);
2169d0ef721eSBaptiste Daroussin rl_linefunc = linefunc;
2170d0ef721eSBaptiste Daroussin el_set(e, EL_UNBUFFERED, 1);
2171d0ef721eSBaptiste Daroussin }
2172d0ef721eSBaptiste Daroussin
2173d0ef721eSBaptiste Daroussin void
rl_callback_handler_remove(void)2174d0ef721eSBaptiste Daroussin rl_callback_handler_remove(void)
2175d0ef721eSBaptiste Daroussin {
217691f76417SBaptiste Daroussin el_set(e, EL_UNBUFFERED, 0);
2177d0ef721eSBaptiste Daroussin rl_linefunc = NULL;
2178d0ef721eSBaptiste Daroussin }
2179d0ef721eSBaptiste Daroussin
2180d0ef721eSBaptiste Daroussin void
rl_redisplay(void)2181d0ef721eSBaptiste Daroussin rl_redisplay(void)
2182d0ef721eSBaptiste Daroussin {
2183d0ef721eSBaptiste Daroussin char a[2];
2184d0ef721eSBaptiste Daroussin a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT];
2185d0ef721eSBaptiste Daroussin a[1] = '\0';
2186d0ef721eSBaptiste Daroussin el_push(e, a);
21877f399375SBaptiste Daroussin rl_forced_update_display();
2188d0ef721eSBaptiste Daroussin }
2189d0ef721eSBaptiste Daroussin
2190d0ef721eSBaptiste Daroussin int
rl_get_previous_history(int count,int key)2191d0ef721eSBaptiste Daroussin rl_get_previous_history(int count, int key)
2192d0ef721eSBaptiste Daroussin {
2193d0ef721eSBaptiste Daroussin char a[2];
2194d0ef721eSBaptiste Daroussin a[0] = (char)key;
2195d0ef721eSBaptiste Daroussin a[1] = '\0';
2196d0ef721eSBaptiste Daroussin while (count--)
2197d0ef721eSBaptiste Daroussin el_push(e, a);
2198d0ef721eSBaptiste Daroussin return 0;
2199d0ef721eSBaptiste Daroussin }
2200d0ef721eSBaptiste Daroussin
2201d0ef721eSBaptiste Daroussin void
2202d0ef721eSBaptiste Daroussin /*ARGSUSED*/
rl_prep_terminal(int meta_flag)2203d0ef721eSBaptiste Daroussin rl_prep_terminal(int meta_flag __attribute__((__unused__)))
2204d0ef721eSBaptiste Daroussin {
2205d0ef721eSBaptiste Daroussin el_set(e, EL_PREP_TERM, 1);
2206d0ef721eSBaptiste Daroussin }
2207d0ef721eSBaptiste Daroussin
2208d0ef721eSBaptiste Daroussin void
rl_deprep_terminal(void)2209d0ef721eSBaptiste Daroussin rl_deprep_terminal(void)
2210d0ef721eSBaptiste Daroussin {
2211d0ef721eSBaptiste Daroussin el_set(e, EL_PREP_TERM, 0);
2212d0ef721eSBaptiste Daroussin }
2213d0ef721eSBaptiste Daroussin
2214d0ef721eSBaptiste Daroussin int
rl_read_init_file(const char * s)2215d0ef721eSBaptiste Daroussin rl_read_init_file(const char *s)
2216d0ef721eSBaptiste Daroussin {
2217d0ef721eSBaptiste Daroussin return el_source(e, s);
2218d0ef721eSBaptiste Daroussin }
2219d0ef721eSBaptiste Daroussin
2220d0ef721eSBaptiste Daroussin int
rl_parse_and_bind(const char * line)2221d0ef721eSBaptiste Daroussin rl_parse_and_bind(const char *line)
2222d0ef721eSBaptiste Daroussin {
2223d0ef721eSBaptiste Daroussin const char **argv;
2224d0ef721eSBaptiste Daroussin int argc;
2225d0ef721eSBaptiste Daroussin Tokenizer *tok;
2226d0ef721eSBaptiste Daroussin
2227d0ef721eSBaptiste Daroussin tok = tok_init(NULL);
2228d0ef721eSBaptiste Daroussin tok_str(tok, line, &argc, &argv);
2229d0ef721eSBaptiste Daroussin argc = el_parse(e, argc, argv);
2230d0ef721eSBaptiste Daroussin tok_end(tok);
2231d0ef721eSBaptiste Daroussin return argc ? 1 : 0;
2232d0ef721eSBaptiste Daroussin }
2233d0ef721eSBaptiste Daroussin
2234d0ef721eSBaptiste Daroussin int
rl_variable_bind(const char * var,const char * value)2235d0ef721eSBaptiste Daroussin rl_variable_bind(const char *var, const char *value)
2236d0ef721eSBaptiste Daroussin {
2237d0ef721eSBaptiste Daroussin /*
2238d0ef721eSBaptiste Daroussin * The proper return value is undocument, but this is what the
2239d0ef721eSBaptiste Daroussin * readline source seems to do.
2240d0ef721eSBaptiste Daroussin */
2241d0ef721eSBaptiste Daroussin return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0;
2242d0ef721eSBaptiste Daroussin }
2243d0ef721eSBaptiste Daroussin
2244d0ef721eSBaptiste Daroussin int
rl_stuff_char(int c)2245d0ef721eSBaptiste Daroussin rl_stuff_char(int c)
2246d0ef721eSBaptiste Daroussin {
2247d0ef721eSBaptiste Daroussin char buf[2];
2248d0ef721eSBaptiste Daroussin
2249d0ef721eSBaptiste Daroussin buf[0] = (char)c;
2250d0ef721eSBaptiste Daroussin buf[1] = '\0';
2251d0ef721eSBaptiste Daroussin el_insertstr(e, buf);
2252d0ef721eSBaptiste Daroussin return 1;
2253d0ef721eSBaptiste Daroussin }
2254d0ef721eSBaptiste Daroussin
2255d0ef721eSBaptiste Daroussin static int
_rl_event_read_char(EditLine * el,wchar_t * wc)2256d0ef721eSBaptiste Daroussin _rl_event_read_char(EditLine *el, wchar_t *wc)
2257d0ef721eSBaptiste Daroussin {
2258d0ef721eSBaptiste Daroussin char ch;
2259d0ef721eSBaptiste Daroussin int n;
2260d0ef721eSBaptiste Daroussin ssize_t num_read = 0;
2261d0ef721eSBaptiste Daroussin
2262d0ef721eSBaptiste Daroussin ch = '\0';
2263d0ef721eSBaptiste Daroussin *wc = L'\0';
2264d0ef721eSBaptiste Daroussin while (rl_event_hook) {
2265d0ef721eSBaptiste Daroussin
2266d0ef721eSBaptiste Daroussin (*rl_event_hook)();
2267d0ef721eSBaptiste Daroussin
2268d0ef721eSBaptiste Daroussin #if defined(FIONREAD)
2269d0ef721eSBaptiste Daroussin if (ioctl(el->el_infd, FIONREAD, &n) < 0)
2270d0ef721eSBaptiste Daroussin return -1;
2271d0ef721eSBaptiste Daroussin if (n)
2272d0ef721eSBaptiste Daroussin num_read = read(el->el_infd, &ch, (size_t)1);
2273d0ef721eSBaptiste Daroussin else
2274d0ef721eSBaptiste Daroussin num_read = 0;
2275d0ef721eSBaptiste Daroussin #elif defined(F_SETFL) && defined(O_NDELAY)
2276d0ef721eSBaptiste Daroussin if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
2277d0ef721eSBaptiste Daroussin return -1;
2278d0ef721eSBaptiste Daroussin if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
2279d0ef721eSBaptiste Daroussin return -1;
2280d0ef721eSBaptiste Daroussin num_read = read(el->el_infd, &ch, 1);
2281d0ef721eSBaptiste Daroussin if (fcntl(el->el_infd, F_SETFL, n))
2282d0ef721eSBaptiste Daroussin return -1;
2283d0ef721eSBaptiste Daroussin #else
2284d0ef721eSBaptiste Daroussin /* not non-blocking, but what you gonna do? */
2285d0ef721eSBaptiste Daroussin num_read = read(el->el_infd, &ch, 1);
2286d0ef721eSBaptiste Daroussin return -1;
2287d0ef721eSBaptiste Daroussin #endif
2288d0ef721eSBaptiste Daroussin
2289d0ef721eSBaptiste Daroussin if (num_read < 0 && errno == EAGAIN)
2290d0ef721eSBaptiste Daroussin continue;
2291d0ef721eSBaptiste Daroussin if (num_read == 0)
2292d0ef721eSBaptiste Daroussin continue;
2293d0ef721eSBaptiste Daroussin break;
2294d0ef721eSBaptiste Daroussin }
2295d0ef721eSBaptiste Daroussin if (!rl_event_hook)
2296d0ef721eSBaptiste Daroussin el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
2297d0ef721eSBaptiste Daroussin *wc = (wchar_t)ch;
2298d0ef721eSBaptiste Daroussin return (int)num_read;
2299d0ef721eSBaptiste Daroussin }
2300d0ef721eSBaptiste Daroussin
2301d0ef721eSBaptiste Daroussin static void
_rl_update_pos(void)2302d0ef721eSBaptiste Daroussin _rl_update_pos(void)
2303d0ef721eSBaptiste Daroussin {
2304d0ef721eSBaptiste Daroussin const LineInfo *li = el_line(e);
2305d0ef721eSBaptiste Daroussin
2306d0ef721eSBaptiste Daroussin rl_point = (int)(li->cursor - li->buffer);
2307d0ef721eSBaptiste Daroussin rl_end = (int)(li->lastchar - li->buffer);
2308d0ef721eSBaptiste Daroussin rl_line_buffer[rl_end] = '\0';
2309d0ef721eSBaptiste Daroussin }
2310d0ef721eSBaptiste Daroussin
23117f399375SBaptiste Daroussin char *
rl_copy_text(int from,int to)23127f399375SBaptiste Daroussin rl_copy_text(int from, int to)
23137f399375SBaptiste Daroussin {
23147f399375SBaptiste Daroussin const LineInfo *li;
23157f399375SBaptiste Daroussin size_t len;
23167f399375SBaptiste Daroussin char * out;
23177f399375SBaptiste Daroussin
23187f399375SBaptiste Daroussin if (h == NULL || e == NULL)
23197f399375SBaptiste Daroussin rl_initialize();
23207f399375SBaptiste Daroussin
23217f399375SBaptiste Daroussin li = el_line(e);
23227f399375SBaptiste Daroussin
23237f399375SBaptiste Daroussin if (from > to)
23247f399375SBaptiste Daroussin return NULL;
23257f399375SBaptiste Daroussin
23267f399375SBaptiste Daroussin if (li->buffer + from > li->lastchar)
23277f399375SBaptiste Daroussin from = (int)(li->lastchar - li->buffer);
23287f399375SBaptiste Daroussin
23297f399375SBaptiste Daroussin if (li->buffer + to > li->lastchar)
23307f399375SBaptiste Daroussin to = (int)(li->lastchar - li->buffer);
23317f399375SBaptiste Daroussin
23327f399375SBaptiste Daroussin len = (size_t)(to - from);
23337f399375SBaptiste Daroussin out = el_malloc((size_t)len + 1);
2334*baff8195SBaptiste Daroussin if (out == NULL)
2335*baff8195SBaptiste Daroussin return NULL;
23367f399375SBaptiste Daroussin (void)strlcpy(out, li->buffer + from , len);
23377f399375SBaptiste Daroussin
23387f399375SBaptiste Daroussin return out;
23397f399375SBaptiste Daroussin }
23407f399375SBaptiste Daroussin
23417f399375SBaptiste Daroussin void
rl_replace_line(const char * text,int clear_undo)23427f399375SBaptiste Daroussin rl_replace_line(const char * text, int clear_undo __attribute__((__unused__)))
23437f399375SBaptiste Daroussin {
23447f399375SBaptiste Daroussin if (!text || *text == 0)
23457f399375SBaptiste Daroussin return;
23467f399375SBaptiste Daroussin
23477f399375SBaptiste Daroussin if (h == NULL || e == NULL)
23487f399375SBaptiste Daroussin rl_initialize();
23497f399375SBaptiste Daroussin
23507f399375SBaptiste Daroussin el_replacestr(e, text);
23517f399375SBaptiste Daroussin }
23527f399375SBaptiste Daroussin
23537f399375SBaptiste Daroussin int
rl_delete_text(int start,int end)23547f399375SBaptiste Daroussin rl_delete_text(int start, int end)
23557f399375SBaptiste Daroussin {
23567f399375SBaptiste Daroussin
23577f399375SBaptiste Daroussin if (h == NULL || e == NULL)
23587f399375SBaptiste Daroussin rl_initialize();
23597f399375SBaptiste Daroussin
23607f399375SBaptiste Daroussin return el_deletestr1(e, start, end);
23617f399375SBaptiste Daroussin }
23627f399375SBaptiste Daroussin
2363d0ef721eSBaptiste Daroussin void
rl_get_screen_size(int * rows,int * cols)2364d0ef721eSBaptiste Daroussin rl_get_screen_size(int *rows, int *cols)
2365d0ef721eSBaptiste Daroussin {
2366d0ef721eSBaptiste Daroussin if (rows)
2367d0ef721eSBaptiste Daroussin el_get(e, EL_GETTC, "li", rows);
2368d0ef721eSBaptiste Daroussin if (cols)
2369d0ef721eSBaptiste Daroussin el_get(e, EL_GETTC, "co", cols);
2370d0ef721eSBaptiste Daroussin }
2371d0ef721eSBaptiste Daroussin
23727f399375SBaptiste Daroussin #define MAX_MESSAGE 160
23737f399375SBaptiste Daroussin void
rl_message(const char * format,...)23747f399375SBaptiste Daroussin rl_message(const char *format, ...)
23757f399375SBaptiste Daroussin {
23767f399375SBaptiste Daroussin char msg[MAX_MESSAGE];
23777f399375SBaptiste Daroussin va_list args;
23787f399375SBaptiste Daroussin
23797f399375SBaptiste Daroussin va_start(args, format);
23807f399375SBaptiste Daroussin vsnprintf(msg, sizeof(msg), format, args);
23817f399375SBaptiste Daroussin va_end(args);
23827f399375SBaptiste Daroussin
23837f399375SBaptiste Daroussin rl_set_prompt(msg);
23847f399375SBaptiste Daroussin rl_forced_update_display();
23857f399375SBaptiste Daroussin }
23867f399375SBaptiste Daroussin
2387d0ef721eSBaptiste Daroussin void
rl_set_screen_size(int rows,int cols)2388d0ef721eSBaptiste Daroussin rl_set_screen_size(int rows, int cols)
2389d0ef721eSBaptiste Daroussin {
2390d0ef721eSBaptiste Daroussin char buf[64];
2391d0ef721eSBaptiste Daroussin (void)snprintf(buf, sizeof(buf), "%d", rows);
2392d0ef721eSBaptiste Daroussin el_set(e, EL_SETTC, "li", buf, NULL);
2393d0ef721eSBaptiste Daroussin (void)snprintf(buf, sizeof(buf), "%d", cols);
2394d0ef721eSBaptiste Daroussin el_set(e, EL_SETTC, "co", buf, NULL);
2395d0ef721eSBaptiste Daroussin }
2396d0ef721eSBaptiste Daroussin
2397d0ef721eSBaptiste Daroussin char **
rl_completion_matches(const char * str,rl_compentry_func_t * fun)2398d0ef721eSBaptiste Daroussin rl_completion_matches(const char *str, rl_compentry_func_t *fun)
2399d0ef721eSBaptiste Daroussin {
2400d0ef721eSBaptiste Daroussin size_t len, max, i, j, min;
2401d0ef721eSBaptiste Daroussin char **list, *match, *a, *b;
2402d0ef721eSBaptiste Daroussin
2403d0ef721eSBaptiste Daroussin len = 1;
2404d0ef721eSBaptiste Daroussin max = 10;
2405d0ef721eSBaptiste Daroussin if ((list = el_calloc(max, sizeof(*list))) == NULL)
2406d0ef721eSBaptiste Daroussin return NULL;
2407d0ef721eSBaptiste Daroussin
2408d0ef721eSBaptiste Daroussin while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
2409d0ef721eSBaptiste Daroussin list[len++] = match;
2410d0ef721eSBaptiste Daroussin if (len == max) {
2411d0ef721eSBaptiste Daroussin char **nl;
2412d0ef721eSBaptiste Daroussin max += 10;
2413d0ef721eSBaptiste Daroussin if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL)
2414d0ef721eSBaptiste Daroussin goto out;
2415d0ef721eSBaptiste Daroussin list = nl;
2416d0ef721eSBaptiste Daroussin }
2417d0ef721eSBaptiste Daroussin }
2418d0ef721eSBaptiste Daroussin if (len == 1)
2419d0ef721eSBaptiste Daroussin goto out;
2420d0ef721eSBaptiste Daroussin list[len] = NULL;
2421d0ef721eSBaptiste Daroussin if (len == 2) {
2422d0ef721eSBaptiste Daroussin if ((list[0] = strdup(list[1])) == NULL)
2423d0ef721eSBaptiste Daroussin goto out;
2424d0ef721eSBaptiste Daroussin return list;
2425d0ef721eSBaptiste Daroussin }
2426d0ef721eSBaptiste Daroussin qsort(&list[1], len - 1, sizeof(*list),
2427d0ef721eSBaptiste Daroussin (int (*)(const void *, const void *)) strcmp);
2428d0ef721eSBaptiste Daroussin min = SIZE_MAX;
2429d0ef721eSBaptiste Daroussin for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
2430d0ef721eSBaptiste Daroussin b = list[i + 1];
2431d0ef721eSBaptiste Daroussin for (j = 0; a[j] && a[j] == b[j]; j++)
2432d0ef721eSBaptiste Daroussin continue;
2433d0ef721eSBaptiste Daroussin if (min > j)
2434d0ef721eSBaptiste Daroussin min = j;
2435d0ef721eSBaptiste Daroussin }
2436d0ef721eSBaptiste Daroussin if (min == 0 && *str) {
2437d0ef721eSBaptiste Daroussin if ((list[0] = strdup(str)) == NULL)
2438d0ef721eSBaptiste Daroussin goto out;
2439d0ef721eSBaptiste Daroussin } else {
2440d0ef721eSBaptiste Daroussin if ((list[0] = el_calloc(min + 1, sizeof(*list[0]))) == NULL)
2441d0ef721eSBaptiste Daroussin goto out;
2442d0ef721eSBaptiste Daroussin (void)memcpy(list[0], list[1], min);
2443d0ef721eSBaptiste Daroussin list[0][min] = '\0';
2444d0ef721eSBaptiste Daroussin }
2445d0ef721eSBaptiste Daroussin return list;
2446d0ef721eSBaptiste Daroussin
2447d0ef721eSBaptiste Daroussin out:
2448d0ef721eSBaptiste Daroussin el_free(list);
2449d0ef721eSBaptiste Daroussin return NULL;
2450d0ef721eSBaptiste Daroussin }
2451d0ef721eSBaptiste Daroussin
2452d0ef721eSBaptiste Daroussin char *
rl_filename_completion_function(const char * text,int state)2453d0ef721eSBaptiste Daroussin rl_filename_completion_function (const char *text, int state)
2454d0ef721eSBaptiste Daroussin {
2455d0ef721eSBaptiste Daroussin return fn_filename_completion_function(text, state);
2456d0ef721eSBaptiste Daroussin }
2457d0ef721eSBaptiste Daroussin
2458d0ef721eSBaptiste Daroussin void
rl_forced_update_display(void)2459d0ef721eSBaptiste Daroussin rl_forced_update_display(void)
2460d0ef721eSBaptiste Daroussin {
2461d0ef721eSBaptiste Daroussin el_set(e, EL_REFRESH);
2462d0ef721eSBaptiste Daroussin }
2463d0ef721eSBaptiste Daroussin
2464d0ef721eSBaptiste Daroussin int
_rl_abort_internal(void)2465d0ef721eSBaptiste Daroussin _rl_abort_internal(void)
2466d0ef721eSBaptiste Daroussin {
2467d0ef721eSBaptiste Daroussin el_beep(e);
2468d0ef721eSBaptiste Daroussin longjmp(topbuf, 1);
2469d0ef721eSBaptiste Daroussin /*NOTREACHED*/
2470d0ef721eSBaptiste Daroussin }
2471d0ef721eSBaptiste Daroussin
2472d0ef721eSBaptiste Daroussin int
_rl_qsort_string_compare(char ** s1,char ** s2)2473d0ef721eSBaptiste Daroussin _rl_qsort_string_compare(char **s1, char **s2)
2474d0ef721eSBaptiste Daroussin {
2475d0ef721eSBaptiste Daroussin return strcoll(*s1, *s2);
2476d0ef721eSBaptiste Daroussin }
2477d0ef721eSBaptiste Daroussin
2478d0ef721eSBaptiste Daroussin HISTORY_STATE *
history_get_history_state(void)2479d0ef721eSBaptiste Daroussin history_get_history_state(void)
2480d0ef721eSBaptiste Daroussin {
2481d0ef721eSBaptiste Daroussin HISTORY_STATE *hs;
2482d0ef721eSBaptiste Daroussin
2483d0ef721eSBaptiste Daroussin if ((hs = el_malloc(sizeof(*hs))) == NULL)
2484d0ef721eSBaptiste Daroussin return NULL;
2485d0ef721eSBaptiste Daroussin hs->length = history_length;
2486d0ef721eSBaptiste Daroussin return hs;
2487d0ef721eSBaptiste Daroussin }
2488d0ef721eSBaptiste Daroussin
2489d0ef721eSBaptiste Daroussin int
2490d0ef721eSBaptiste Daroussin /*ARGSUSED*/
rl_kill_text(int from,int to)2491d0ef721eSBaptiste Daroussin rl_kill_text(int from __attribute__((__unused__)),
2492d0ef721eSBaptiste Daroussin int to __attribute__((__unused__)))
2493d0ef721eSBaptiste Daroussin {
2494d0ef721eSBaptiste Daroussin return 0;
2495d0ef721eSBaptiste Daroussin }
2496d0ef721eSBaptiste Daroussin
2497d0ef721eSBaptiste Daroussin Keymap
rl_make_bare_keymap(void)2498d0ef721eSBaptiste Daroussin rl_make_bare_keymap(void)
2499d0ef721eSBaptiste Daroussin {
2500d0ef721eSBaptiste Daroussin return NULL;
2501d0ef721eSBaptiste Daroussin }
2502d0ef721eSBaptiste Daroussin
2503d0ef721eSBaptiste Daroussin Keymap
rl_get_keymap(void)2504d0ef721eSBaptiste Daroussin rl_get_keymap(void)
2505d0ef721eSBaptiste Daroussin {
2506d0ef721eSBaptiste Daroussin return NULL;
2507d0ef721eSBaptiste Daroussin }
2508d0ef721eSBaptiste Daroussin
2509d0ef721eSBaptiste Daroussin void
2510d0ef721eSBaptiste Daroussin /*ARGSUSED*/
rl_set_keymap(Keymap k)2511d0ef721eSBaptiste Daroussin rl_set_keymap(Keymap k __attribute__((__unused__)))
2512d0ef721eSBaptiste Daroussin {
2513d0ef721eSBaptiste Daroussin }
2514d0ef721eSBaptiste Daroussin
2515d0ef721eSBaptiste Daroussin int
2516d0ef721eSBaptiste Daroussin /*ARGSUSED*/
rl_generic_bind(int type,const char * keyseq,const char * data,Keymap k)2517d0ef721eSBaptiste Daroussin rl_generic_bind(int type __attribute__((__unused__)),
2518d0ef721eSBaptiste Daroussin const char * keyseq __attribute__((__unused__)),
2519d0ef721eSBaptiste Daroussin const char * data __attribute__((__unused__)),
2520d0ef721eSBaptiste Daroussin Keymap k __attribute__((__unused__)))
2521d0ef721eSBaptiste Daroussin {
2522d0ef721eSBaptiste Daroussin return 0;
2523d0ef721eSBaptiste Daroussin }
2524d0ef721eSBaptiste Daroussin
2525d0ef721eSBaptiste Daroussin int
2526d0ef721eSBaptiste Daroussin /*ARGSUSED*/
rl_bind_key_in_map(int key,rl_command_func_t * fun,Keymap k)2527d0ef721eSBaptiste Daroussin rl_bind_key_in_map(int key __attribute__((__unused__)),
2528d0ef721eSBaptiste Daroussin rl_command_func_t *fun __attribute__((__unused__)),
2529d0ef721eSBaptiste Daroussin Keymap k __attribute__((__unused__)))
2530d0ef721eSBaptiste Daroussin {
2531d0ef721eSBaptiste Daroussin return 0;
2532d0ef721eSBaptiste Daroussin }
2533d0ef721eSBaptiste Daroussin
25347f399375SBaptiste Daroussin int
rl_set_key(const char * keyseq,rl_command_func_t * function,Keymap k)25357f399375SBaptiste Daroussin rl_set_key(const char *keyseq __attribute__((__unused__)),
25367f399375SBaptiste Daroussin rl_command_func_t *function __attribute__((__unused__)),
25377f399375SBaptiste Daroussin Keymap k __attribute__((__unused__)))
25387f399375SBaptiste Daroussin {
25397f399375SBaptiste Daroussin return 0;
25407f399375SBaptiste Daroussin }
25417f399375SBaptiste Daroussin
2542d0ef721eSBaptiste Daroussin /* unsupported, but needed by python */
2543d0ef721eSBaptiste Daroussin void
rl_cleanup_after_signal(void)2544d0ef721eSBaptiste Daroussin rl_cleanup_after_signal(void)
2545d0ef721eSBaptiste Daroussin {
2546d0ef721eSBaptiste Daroussin }
2547d0ef721eSBaptiste Daroussin
2548d0ef721eSBaptiste Daroussin int
rl_on_new_line(void)2549d0ef721eSBaptiste Daroussin rl_on_new_line(void)
2550d0ef721eSBaptiste Daroussin {
2551d0ef721eSBaptiste Daroussin return 0;
2552d0ef721eSBaptiste Daroussin }
2553d0ef721eSBaptiste Daroussin
2554d0ef721eSBaptiste Daroussin void
rl_free_line_state(void)2555d0ef721eSBaptiste Daroussin rl_free_line_state(void)
2556d0ef721eSBaptiste Daroussin {
2557d0ef721eSBaptiste Daroussin }
2558d0ef721eSBaptiste Daroussin
2559d0ef721eSBaptiste Daroussin int
2560d0ef721eSBaptiste Daroussin /*ARGSUSED*/
rl_set_keyboard_input_timeout(int u)2561d0ef721eSBaptiste Daroussin rl_set_keyboard_input_timeout(int u __attribute__((__unused__)))
2562d0ef721eSBaptiste Daroussin {
2563d0ef721eSBaptiste Daroussin return 0;
2564d0ef721eSBaptiste Daroussin }
2565d0ef721eSBaptiste Daroussin
2566d0ef721eSBaptiste Daroussin void
rl_resize_terminal(void)2567d0ef721eSBaptiste Daroussin rl_resize_terminal(void)
2568d0ef721eSBaptiste Daroussin {
2569d0ef721eSBaptiste Daroussin el_resize(e);
2570d0ef721eSBaptiste Daroussin }
2571d0ef721eSBaptiste Daroussin
2572d0ef721eSBaptiste Daroussin void
rl_reset_after_signal(void)2573d0ef721eSBaptiste Daroussin rl_reset_after_signal(void)
2574d0ef721eSBaptiste Daroussin {
2575d0ef721eSBaptiste Daroussin if (rl_prep_term_function)
2576d0ef721eSBaptiste Daroussin (*rl_prep_term_function)();
2577d0ef721eSBaptiste Daroussin }
2578d0ef721eSBaptiste Daroussin
2579d0ef721eSBaptiste Daroussin void
rl_echo_signal_char(int sig)2580d0ef721eSBaptiste Daroussin rl_echo_signal_char(int sig)
2581d0ef721eSBaptiste Daroussin {
2582d0ef721eSBaptiste Daroussin int c = tty_get_signal_character(e, sig);
2583d0ef721eSBaptiste Daroussin if (c == -1)
2584d0ef721eSBaptiste Daroussin return;
2585d0ef721eSBaptiste Daroussin re_putc(e, c, 0);
2586d0ef721eSBaptiste Daroussin }
258791f76417SBaptiste Daroussin
258891f76417SBaptiste Daroussin int
rl_crlf(void)258991f76417SBaptiste Daroussin rl_crlf(void)
259091f76417SBaptiste Daroussin {
259191f76417SBaptiste Daroussin re_putc(e, '\n', 0);
259291f76417SBaptiste Daroussin return 0;
259391f76417SBaptiste Daroussin }
259491f76417SBaptiste Daroussin
259591f76417SBaptiste Daroussin int
rl_ding(void)259691f76417SBaptiste Daroussin rl_ding(void)
259791f76417SBaptiste Daroussin {
259891f76417SBaptiste Daroussin re_putc(e, '\a', 0);
259991f76417SBaptiste Daroussin return 0;
260091f76417SBaptiste Daroussin }
260191f76417SBaptiste Daroussin
260291f76417SBaptiste Daroussin int
rl_abort(int count,int key)260391f76417SBaptiste Daroussin rl_abort(int count, int key)
260491f76417SBaptiste Daroussin {
260591f76417SBaptiste Daroussin return count && key ? 0 : 0;
260691f76417SBaptiste Daroussin }
260791f76417SBaptiste Daroussin
260891f76417SBaptiste Daroussin int
rl_set_keymap_name(const char * name,Keymap k)260991f76417SBaptiste Daroussin rl_set_keymap_name(const char *name, Keymap k)
261091f76417SBaptiste Daroussin {
261191f76417SBaptiste Daroussin return name && k ? 0 : 0;
261291f76417SBaptiste Daroussin }
261391f76417SBaptiste Daroussin
261491f76417SBaptiste Daroussin histdata_t
free_history_entry(HIST_ENTRY * he)261591f76417SBaptiste Daroussin free_history_entry(HIST_ENTRY *he)
261691f76417SBaptiste Daroussin {
261791f76417SBaptiste Daroussin return he ? NULL : NULL;
261891f76417SBaptiste Daroussin }
261991f76417SBaptiste Daroussin
262091f76417SBaptiste Daroussin void
_rl_erase_entire_line(void)262191f76417SBaptiste Daroussin _rl_erase_entire_line(void)
262291f76417SBaptiste Daroussin {
262391f76417SBaptiste Daroussin }
2624