Sat Feb 19 17:45:02 2022 UTC ()
PR/56695: Walter Lozano: Correct declaration of hook functions.


(christos)
diff -r1.172 -r1.173 src/lib/libedit/readline.c
diff -r1.52 -r1.53 src/lib/libedit/readline/readline.h

cvs diff -r1.172 -r1.173 src/lib/libedit/readline.c (switch to unified diff)

--- src/lib/libedit/readline.c 2022/02/08 15:05:10 1.172
+++ src/lib/libedit/readline.c 2022/02/19 17:45:02 1.173
@@ -1,1462 +1,1462 @@ @@ -1,1462 +1,1462 @@
1/* $NetBSD: readline.c,v 1.172 2022/02/08 15:05:10 christos Exp $ */ 1/* $NetBSD: readline.c,v 1.173 2022/02/19 17:45:02 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jaromir Dolecek. 8 * by Jaromir Dolecek.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include "config.h" 32#include "config.h"
33#if !defined(lint) && !defined(SCCSID) 33#if !defined(lint) && !defined(SCCSID)
34__RCSID("$NetBSD: readline.c,v 1.172 2022/02/08 15:05:10 christos Exp $"); 34__RCSID("$NetBSD: readline.c,v 1.173 2022/02/19 17:45:02 christos Exp $");
35#endif /* not lint && not SCCSID */ 35#endif /* not lint && not SCCSID */
36 36
37#include <sys/types.h> 37#include <sys/types.h>
38#include <sys/stat.h> 38#include <sys/stat.h>
39#include <ctype.h> 39#include <ctype.h>
40#include <dirent.h> 40#include <dirent.h>
41#include <errno.h> 41#include <errno.h>
42#include <fcntl.h> 42#include <fcntl.h>
43#include <limits.h> 43#include <limits.h>
44#include <pwd.h> 44#include <pwd.h>
45#include <setjmp.h> 45#include <setjmp.h>
46#include <stdarg.h> 46#include <stdarg.h>
47#include <stdint.h> 47#include <stdint.h>
48#include <stdio.h> 48#include <stdio.h>
49#include <stdlib.h> 49#include <stdlib.h>
50#include <string.h> 50#include <string.h>
51#include <unistd.h> 51#include <unistd.h>
52#include <vis.h> 52#include <vis.h>
53 53
54#include "readline/readline.h" 54#include "readline/readline.h"
55#include "el.h" 55#include "el.h"
56#include "fcns.h" 56#include "fcns.h"
57#include "filecomplete.h" 57#include "filecomplete.h"
58 58
59void rl_prep_terminal(int); 59void rl_prep_terminal(int);
60void rl_deprep_terminal(void); 60void rl_deprep_terminal(void);
61 61
62/* for rl_complete() */ 62/* for rl_complete() */
63#define TAB '\r' 63#define TAB '\r'
64 64
65/* see comment at the #ifdef for sense of this */ 65/* see comment at the #ifdef for sense of this */
66/* #define GDB_411_HACK */ 66/* #define GDB_411_HACK */
67 67
68/* readline compatibility stuff - look at readline sources/documentation */ 68/* readline compatibility stuff - look at readline sources/documentation */
69/* to see what these variables mean */ 69/* to see what these variables mean */
70const char *rl_library_version = "EditLine wrapper"; 70const char *rl_library_version = "EditLine wrapper";
71int rl_readline_version = RL_READLINE_VERSION; 71int rl_readline_version = RL_READLINE_VERSION;
72static char empty[] = { '\0' }; 72static char empty[] = { '\0' };
73static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; 73static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
74static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', 74static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
75 '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; 75 '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
76const char *rl_readline_name = empty; 76const char *rl_readline_name = empty;
77FILE *rl_instream = NULL; 77FILE *rl_instream = NULL;
78FILE *rl_outstream = NULL; 78FILE *rl_outstream = NULL;
79int rl_point = 0; 79int rl_point = 0;
80int rl_end = 0; 80int rl_end = 0;
81char *rl_line_buffer = NULL; 81char *rl_line_buffer = NULL;
82rl_vcpfunc_t *rl_linefunc = NULL; 82rl_vcpfunc_t *rl_linefunc = NULL;
83int rl_done = 0; 83int rl_done = 0;
84rl_hook_func_t *rl_event_hook = NULL; 84rl_hook_func_t *rl_event_hook = NULL;
85KEYMAP_ENTRY_ARRAY emacs_standard_keymap, 85KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
86 emacs_meta_keymap, 86 emacs_meta_keymap,
87 emacs_ctlx_keymap; 87 emacs_ctlx_keymap;
88/* 88/*
89 * The following is not implemented; we always catch signals in the 89 * The following is not implemented; we always catch signals in the
90 * libedit fashion: set handlers on entry to el_gets() and clear them 90 * libedit fashion: set handlers on entry to el_gets() and clear them
91 * on the way out. This simplistic approach works for most cases; if 91 * on the way out. This simplistic approach works for most cases; if
92 * it does not work for your application, please let us know. 92 * it does not work for your application, please let us know.
93 */ 93 */
94int rl_catch_signals = 1; 94int rl_catch_signals = 1;
95int rl_catch_sigwinch = 1; 95int rl_catch_sigwinch = 1;
96 96
97int history_base = 1; /* probably never subject to change */ 97int history_base = 1; /* probably never subject to change */
98int history_length = 0; 98int history_length = 0;
99int history_offset = 0; 99int history_offset = 0;
100int max_input_history = 0; 100int max_input_history = 0;
101char history_expansion_char = '!'; 101char history_expansion_char = '!';
102char history_subst_char = '^'; 102char history_subst_char = '^';
103char *history_no_expand_chars = expand_chars; 103char *history_no_expand_chars = expand_chars;
104Function *history_inhibit_expansion_function = NULL; 104Function *history_inhibit_expansion_function = NULL;
105char *history_arg_extract(int start, int end, const char *str); 105char *history_arg_extract(int start, int end, const char *str);
106 106
107int rl_inhibit_completion = 0; 107int rl_inhibit_completion = 0;
108int rl_attempted_completion_over = 0; 108int rl_attempted_completion_over = 0;
109const char *rl_basic_word_break_characters = break_chars; 109const char *rl_basic_word_break_characters = break_chars;
110char *rl_completer_word_break_characters = NULL; 110char *rl_completer_word_break_characters = NULL;
111const char *rl_completer_quote_characters = NULL; 111const char *rl_completer_quote_characters = NULL;
112const char *rl_basic_quote_characters = "\"'"; 112const char *rl_basic_quote_characters = "\"'";
113rl_compentry_func_t *rl_completion_entry_function = NULL; 113rl_compentry_func_t *rl_completion_entry_function = NULL;
114char *(*rl_completion_word_break_hook)(void) = NULL; 114char *(*rl_completion_word_break_hook)(void) = NULL;
115rl_completion_func_t *rl_attempted_completion_function = NULL; 115rl_completion_func_t *rl_attempted_completion_function = NULL;
116Function *rl_pre_input_hook = NULL; 116rl_hook_func_t *rl_pre_input_hook = NULL;
117Function *rl_startup1_hook = NULL; 117rl_hook_func_t *rl_startup1_hook = NULL;
118int (*rl_getc_function)(FILE *) = NULL; 118int (*rl_getc_function)(FILE *) = NULL;
119char *rl_terminal_name = NULL; 119char *rl_terminal_name = NULL;
120int rl_already_prompted = 0; 120int rl_already_prompted = 0;
121int rl_filename_completion_desired = 0; 121int rl_filename_completion_desired = 0;
122int rl_ignore_completion_duplicates = 0; 122int rl_ignore_completion_duplicates = 0;
123int readline_echoing_p = 1; 123int readline_echoing_p = 1;
124int _rl_print_completions_horizontally = 0; 124int _rl_print_completions_horizontally = 0;
125VFunction *rl_redisplay_function = NULL; 125VFunction *rl_redisplay_function = NULL;
126Function *rl_startup_hook = NULL; 126rl_hook_func_t *rl_startup_hook = NULL;
127VFunction *rl_completion_display_matches_hook = NULL; 127VFunction *rl_completion_display_matches_hook = NULL;
128VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; 128VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
129VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; 129VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
130KEYMAP_ENTRY_ARRAY emacs_meta_keymap; 130KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
131unsigned long rl_readline_state = RL_STATE_NONE; 131unsigned long rl_readline_state = RL_STATE_NONE;
132int _rl_complete_mark_directories; 132int _rl_complete_mark_directories;
133rl_icppfunc_t *rl_directory_completion_hook; 133rl_icppfunc_t *rl_directory_completion_hook;
134int rl_completion_suppress_append; 134int rl_completion_suppress_append;
135int rl_sort_completion_matches; 135int rl_sort_completion_matches;
136int _rl_completion_prefix_display_length; 136int _rl_completion_prefix_display_length;
137int _rl_echoing_p; 137int _rl_echoing_p;
138int history_max_entries; 138int history_max_entries;
139char *rl_display_prompt; 139char *rl_display_prompt;
140int rl_erase_empty_line; 140int rl_erase_empty_line;
141 141
142/* 142/*
143 * The current prompt string. 143 * The current prompt string.
144 */ 144 */
145char *rl_prompt = NULL; 145char *rl_prompt = NULL;
146char *rl_prompt_saved = NULL; 146char *rl_prompt_saved = NULL;
147/* 147/*
148 * This is set to character indicating type of completion being done by 148 * This is set to character indicating type of completion being done by
149 * rl_complete_internal(); this is available for application completion 149 * rl_complete_internal(); this is available for application completion
150 * functions. 150 * functions.
151 */ 151 */
152int rl_completion_type = 0; 152int rl_completion_type = 0;
153 153
154/* 154/*
155 * If more than this number of items results from query for possible 155 * If more than this number of items results from query for possible
156 * completions, we ask user if they are sure to really display the list. 156 * completions, we ask user if they are sure to really display the list.
157 */ 157 */
158int rl_completion_query_items = 100; 158int rl_completion_query_items = 100;
159 159
160/* 160/*
161 * List of characters which are word break characters, but should be left 161 * List of characters which are word break characters, but should be left
162 * in the parsed text when it is passed to the completion function. 162 * in the parsed text when it is passed to the completion function.
163 * Shell uses this to help determine what kind of completing to do. 163 * Shell uses this to help determine what kind of completing to do.
164 */ 164 */
165const char *rl_special_prefixes = NULL; 165const char *rl_special_prefixes = NULL;
166 166
167/* 167/*
168 * This is the character appended to the completed words if at the end of 168 * This is the character appended to the completed words if at the end of
169 * the line. Default is ' ' (a space). 169 * the line. Default is ' ' (a space).
170 */ 170 */
171int rl_completion_append_character = ' '; 171int rl_completion_append_character = ' ';
172 172
173/* stuff below is used internally by libedit for readline emulation */ 173/* stuff below is used internally by libedit for readline emulation */
174 174
175static History *h = NULL; 175static History *h = NULL;
176static EditLine *e = NULL; 176static EditLine *e = NULL;
177static rl_command_func_t *map[256]; 177static rl_command_func_t *map[256];
178static jmp_buf topbuf; 178static jmp_buf topbuf;
179 179
180/* internal functions */ 180/* internal functions */
181static unsigned char _el_rl_complete(EditLine *, int); 181static unsigned char _el_rl_complete(EditLine *, int);
182static unsigned char _el_rl_tstp(EditLine *, int); 182static unsigned char _el_rl_tstp(EditLine *, int);
183static char *_get_prompt(EditLine *); 183static char *_get_prompt(EditLine *);
184static int _getc_function(EditLine *, wchar_t *); 184static int _getc_function(EditLine *, wchar_t *);
185static int _history_expand_command(const char *, size_t, size_t, 185static int _history_expand_command(const char *, size_t, size_t,
186 char **); 186 char **);
187static char *_rl_compat_sub(const char *, const char *, 187static char *_rl_compat_sub(const char *, const char *,
188 const char *, int); 188 const char *, int);
189static int _rl_event_read_char(EditLine *, wchar_t *); 189static int _rl_event_read_char(EditLine *, wchar_t *);
190static void _rl_update_pos(void); 190static void _rl_update_pos(void);
191 191
192static HIST_ENTRY rl_he; 192static HIST_ENTRY rl_he;
193 193
194/* ARGSUSED */ 194/* ARGSUSED */
195static char * 195static char *
196_get_prompt(EditLine *el __attribute__((__unused__))) 196_get_prompt(EditLine *el __attribute__((__unused__)))
197{ 197{
198 rl_already_prompted = 1; 198 rl_already_prompted = 1;
199 return rl_prompt; 199 return rl_prompt;
200} 200}
201 201
202 202
203/* 203/*
204 * read one key from user defined input function 204 * read one key from user defined input function
205 */ 205 */
206static int 206static int
207/*ARGSUSED*/ 207/*ARGSUSED*/
208_getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c) 208_getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c)
209{ 209{
210 int i; 210 int i;
211 211
212 i = (*rl_getc_function)(rl_instream); 212 i = (*rl_getc_function)(rl_instream);
213 if (i == -1) 213 if (i == -1)
214 return 0; 214 return 0;
215 *c = (wchar_t)i; 215 *c = (wchar_t)i;
216 return 1; 216 return 1;
217} 217}
218 218
219static void 219static void
220_resize_fun(EditLine *el, void *a) 220_resize_fun(EditLine *el, void *a)
221{ 221{
222 const LineInfo *li; 222 const LineInfo *li;
223 const char **ap = a; 223 const char **ap = a;
224 224
225 li = el_line(el); 225 li = el_line(el);
226 *ap = li->buffer; 226 *ap = li->buffer;
227} 227}
228 228
229static const char * 229static const char *
230_default_history_file(void) 230_default_history_file(void)
231{ 231{
232 struct passwd *p; 232 struct passwd *p;
233 static char *path; 233 static char *path;
234 size_t len; 234 size_t len;
235 235
236 if (path) 236 if (path)
237 return path; 237 return path;
238 238
239 if ((p = getpwuid(getuid())) == NULL) 239 if ((p = getpwuid(getuid())) == NULL)
240 return NULL; 240 return NULL;
241 241
242 len = strlen(p->pw_dir) + sizeof("/.history"); 242 len = strlen(p->pw_dir) + sizeof("/.history");
243 if ((path = malloc(len)) == NULL) 243 if ((path = malloc(len)) == NULL)
244 return NULL; 244 return NULL;
245 245
246 (void)snprintf(path, len, "%s/.history", p->pw_dir); 246 (void)snprintf(path, len, "%s/.history", p->pw_dir);
247 return path; 247 return path;
248} 248}
249 249
250/* 250/*
251 * READLINE compatibility stuff 251 * READLINE compatibility stuff
252 */ 252 */
253 253
254/* 254/*
255 * Set the prompt 255 * Set the prompt
256 */ 256 */
257int 257int
258rl_set_prompt(const char *prompt) 258rl_set_prompt(const char *prompt)
259{ 259{
260 char *p; 260 char *p;
261 261
262 if (!prompt) 262 if (!prompt)
263 prompt = ""; 263 prompt = "";
264 if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) 264 if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
265 return 0; 265 return 0;
266 if (rl_prompt) 266 if (rl_prompt)
267 el_free(rl_prompt); 267 el_free(rl_prompt);
268 rl_prompt = strdup(prompt); 268 rl_prompt = strdup(prompt);
269 if (rl_prompt == NULL) 269 if (rl_prompt == NULL)
270 return -1; 270 return -1;
271 271
272 while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) { 272 while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) {
273 /* Remove adjacent end/start markers to avoid double-escapes. */ 273 /* Remove adjacent end/start markers to avoid double-escapes. */
274 if (p[1] == RL_PROMPT_START_IGNORE) { 274 if (p[1] == RL_PROMPT_START_IGNORE) {
275 memmove(p, p + 2, 1 + strlen(p + 2)); 275 memmove(p, p + 2, 1 + strlen(p + 2));
276 } else { 276 } else {
277 *p = RL_PROMPT_START_IGNORE; 277 *p = RL_PROMPT_START_IGNORE;
278 } 278 }
279 } 279 }
280 280
281 return 0; 281 return 0;
282} 282}
283 283
284void 284void
285rl_save_prompt(void) 285rl_save_prompt(void)
286{ 286{
287 rl_prompt_saved = strdup(rl_prompt); 287 rl_prompt_saved = strdup(rl_prompt);
288} 288}
289 289
290void 290void
291rl_restore_prompt(void) 291rl_restore_prompt(void)
292{ 292{
293 if (!rl_prompt_saved) 293 if (!rl_prompt_saved)
294 return; 294 return;
295 rl_prompt = rl_prompt_saved; 295 rl_prompt = rl_prompt_saved;
296 rl_prompt_saved = NULL; 296 rl_prompt_saved = NULL;
297} 297}
298 298
299/* 299/*
300 * initialize rl compat stuff 300 * initialize rl compat stuff
301 */ 301 */
302int 302int
303rl_initialize(void) 303rl_initialize(void)
304{ 304{
305 HistEvent ev; 305 HistEvent ev;
306 int editmode = 1; 306 int editmode = 1;
307 struct termios t; 307 struct termios t;
308 308
309 if (e != NULL) 309 if (e != NULL)
310 el_end(e); 310 el_end(e);
311 if (h != NULL) 311 if (h != NULL)
312 history_end(h); 312 history_end(h);
313 313
314 RL_UNSETSTATE(RL_STATE_DONE); 314 RL_UNSETSTATE(RL_STATE_DONE);
315 315
316 if (!rl_instream) 316 if (!rl_instream)
317 rl_instream = stdin; 317 rl_instream = stdin;
318 if (!rl_outstream) 318 if (!rl_outstream)
319 rl_outstream = stdout; 319 rl_outstream = stdout;
320 320
321 /* 321 /*
322 * See if we don't really want to run the editor 322 * See if we don't really want to run the editor
323 */ 323 */
324 if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0) 324 if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
325 editmode = 0; 325 editmode = 0;
326 326
327 e = el_init_internal(rl_readline_name, rl_instream, rl_outstream, 327 e = el_init_internal(rl_readline_name, rl_instream, rl_outstream,
328 stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr), 328 stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr),
329 NO_RESET); 329 NO_RESET);
330 330
331 if (!editmode) 331 if (!editmode)
332 el_set(e, EL_EDITMODE, 0); 332 el_set(e, EL_EDITMODE, 0);
333 333
334 h = history_init(); 334 h = history_init();
335 if (!e || !h) 335 if (!e || !h)
336 return -1; 336 return -1;
337 337
338 history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ 338 history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
339 history_length = 0; 339 history_length = 0;
340 max_input_history = INT_MAX; 340 max_input_history = INT_MAX;
341 el_set(e, EL_HIST, history, h); 341 el_set(e, EL_HIST, history, h);
342 342
343 /* Setup resize function */ 343 /* Setup resize function */
344 el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer); 344 el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer);
345 345
346 /* setup getc function if valid */ 346 /* setup getc function if valid */
347 if (rl_getc_function) 347 if (rl_getc_function)
348 el_set(e, EL_GETCFN, _getc_function); 348 el_set(e, EL_GETCFN, _getc_function);
349 349
350 /* for proper prompt printing in readline() */ 350 /* for proper prompt printing in readline() */
351 if (rl_set_prompt("") == -1) { 351 if (rl_set_prompt("") == -1) {
352 history_end(h); 352 history_end(h);
353 el_end(e); 353 el_end(e);
354 return -1; 354 return -1;
355 } 355 }
356 el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE); 356 el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE);
357 el_set(e, EL_SIGNAL, rl_catch_signals); 357 el_set(e, EL_SIGNAL, rl_catch_signals);
358 358
359 /* set default mode to "emacs"-style and read setting afterwards */ 359 /* set default mode to "emacs"-style and read setting afterwards */
360 /* so this can be overridden */ 360 /* so this can be overridden */
361 el_set(e, EL_EDITOR, "emacs"); 361 el_set(e, EL_EDITOR, "emacs");
362 if (rl_terminal_name != NULL) 362 if (rl_terminal_name != NULL)
363 el_set(e, EL_TERMINAL, rl_terminal_name); 363 el_set(e, EL_TERMINAL, rl_terminal_name);
364 else 364 else
365 el_get(e, EL_TERMINAL, &rl_terminal_name); 365 el_get(e, EL_TERMINAL, &rl_terminal_name);
366 366
367 /* 367 /*
368 * Word completion - this has to go AFTER rebinding keys 368 * Word completion - this has to go AFTER rebinding keys
369 * to emacs-style. 369 * to emacs-style.
370 */ 370 */
371 el_set(e, EL_ADDFN, "rl_complete", 371 el_set(e, EL_ADDFN, "rl_complete",
372 "ReadLine compatible completion function", 372 "ReadLine compatible completion function",
373 _el_rl_complete); 373 _el_rl_complete);
374 el_set(e, EL_BIND, "^I", "rl_complete", NULL); 374 el_set(e, EL_BIND, "^I", "rl_complete", NULL);
375 375
376 /* 376 /*
377 * Send TSTP when ^Z is pressed. 377 * Send TSTP when ^Z is pressed.
378 */ 378 */
379 el_set(e, EL_ADDFN, "rl_tstp", 379 el_set(e, EL_ADDFN, "rl_tstp",
380 "ReadLine compatible suspend function", 380 "ReadLine compatible suspend function",
381 _el_rl_tstp); 381 _el_rl_tstp);
382 el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); 382 el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
383 383
384 /* 384 /*
385 * Set some readline compatible key-bindings. 385 * Set some readline compatible key-bindings.
386 */ 386 */
387 el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL); 387 el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL);
388 388
389 /* 389 /*
390 * Allow the use of Home/End keys. 390 * Allow the use of Home/End keys.
391 */ 391 */
392 el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL); 392 el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
393 el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL); 393 el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
394 el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL); 394 el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL);
395 el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL); 395 el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL);
396 el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL); 396 el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL);
397 el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL); 397 el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL);
398 398
399 /* 399 /*
400 * Allow the use of the Delete/Insert keys. 400 * Allow the use of the Delete/Insert keys.
401 */ 401 */
402 el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL); 402 el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
403 el_set(e, EL_BIND, "\\e[2~", "ed-quoted-insert", NULL); 403 el_set(e, EL_BIND, "\\e[2~", "ed-quoted-insert", NULL);
404 404
405 /* 405 /*
406 * Ctrl-left-arrow and Ctrl-right-arrow for word moving. 406 * Ctrl-left-arrow and Ctrl-right-arrow for word moving.
407 */ 407 */
408 el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL); 408 el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
409 el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL); 409 el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
410 el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL); 410 el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL);
411 el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL); 411 el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL);
412 el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL); 412 el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
413 el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL); 413 el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
414 414
415 /* read settings from configuration file */ 415 /* read settings from configuration file */
416 el_source(e, NULL); 416 el_source(e, NULL);
417 417
418 /* 418 /*
419 * Unfortunately, some applications really do use rl_point 419 * Unfortunately, some applications really do use rl_point
420 * and rl_line_buffer directly. 420 * and rl_line_buffer directly.
421 */ 421 */
422 _resize_fun(e, &rl_line_buffer); 422 _resize_fun(e, &rl_line_buffer);
423 _rl_update_pos(); 423 _rl_update_pos();
424 424
425 tty_end(e, TCSADRAIN); 425 tty_end(e, TCSADRAIN);
426 426
427 return 0; 427 return 0;
428} 428}
429 429
430 430
431/* 431/*
432 * read one line from input stream and return it, chomping 432 * read one line from input stream and return it, chomping
433 * trailing newline (if there is any) 433 * trailing newline (if there is any)
434 */ 434 */
435char * 435char *
436readline(const char *p) 436readline(const char *p)
437{ 437{
438 HistEvent ev; 438 HistEvent ev;
439 const char * volatile prompt = p; 439 const char * volatile prompt = p;
440 int count; 440 int count;
441 const char *ret; 441 const char *ret;
442 char *buf; 442 char *buf;
443 static int used_event_hook; 443 static int used_event_hook;
444 444
445 if (e == NULL || h == NULL) 445 if (e == NULL || h == NULL)
446 rl_initialize(); 446 rl_initialize();
447 if (rl_startup_hook) { 447 if (rl_startup_hook) {
448 (*rl_startup_hook)(NULL, 0); 448 (*rl_startup_hook)();
449 } 449 }
450 tty_init(e); 450 tty_init(e);
451 451
452 452
453 rl_done = 0; 453 rl_done = 0;
454 454
455 (void)setjmp(topbuf); 455 (void)setjmp(topbuf);
456 buf = NULL; 456 buf = NULL;
457 457
458 /* update prompt accordingly to what has been passed */ 458 /* update prompt accordingly to what has been passed */
459 if (rl_set_prompt(prompt) == -1) 459 if (rl_set_prompt(prompt) == -1)
460 goto out; 460 goto out;
461 461
462 if (rl_pre_input_hook) 462 if (rl_pre_input_hook)
463 (*rl_pre_input_hook)(NULL, 0); 463 (*rl_pre_input_hook)();
464 464
465 if (rl_event_hook && !(e->el_flags & NO_TTY)) { 465 if (rl_event_hook && !(e->el_flags & NO_TTY)) {
466 el_set(e, EL_GETCFN, _rl_event_read_char); 466 el_set(e, EL_GETCFN, _rl_event_read_char);
467 used_event_hook = 1; 467 used_event_hook = 1;
468 } 468 }
469 469
470 if (!rl_event_hook && used_event_hook) { 470 if (!rl_event_hook && used_event_hook) {
471 el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN); 471 el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
472 used_event_hook = 0; 472 used_event_hook = 0;
473 } 473 }
474 474
475 rl_already_prompted = 0; 475 rl_already_prompted = 0;
476 476
477 /* get one line from input stream */ 477 /* get one line from input stream */
478 ret = el_gets(e, &count); 478 ret = el_gets(e, &count);
479 479
480 if (ret && count > 0) { 480 if (ret && count > 0) {
481 buf = strdup(ret); 481 buf = strdup(ret);
482 if (buf == NULL) 482 if (buf == NULL)
483 goto out; 483 goto out;
484 buf[strcspn(buf, "\n")] = '\0'; 484 buf[strcspn(buf, "\n")] = '\0';
485 } else 485 } else
486 buf = NULL; 486 buf = NULL;
487 487
488 history(h, &ev, H_GETSIZE); 488 history(h, &ev, H_GETSIZE);
489 history_length = ev.num; 489 history_length = ev.num;
490 490
491out: 491out:
492 tty_end(e, TCSADRAIN); 492 tty_end(e, TCSADRAIN);
493 return buf; 493 return buf;
494} 494}
495 495
496/* 496/*
497 * history functions 497 * history functions
498 */ 498 */
499 499
500/* 500/*
501 * is normally called before application starts to use 501 * is normally called before application starts to use
502 * history expansion functions 502 * history expansion functions
503 */ 503 */
504void 504void
505using_history(void) 505using_history(void)
506{ 506{
507 if (h == NULL || e == NULL) 507 if (h == NULL || e == NULL)
508 rl_initialize(); 508 rl_initialize();
509 history_offset = history_length; 509 history_offset = history_length;
510} 510}
511 511
512 512
513/* 513/*
514 * substitute ``what'' with ``with'', returning resulting string; if 514 * substitute ``what'' with ``with'', returning resulting string; if
515 * globally == 1, substitutes all occurrences of what, otherwise only the 515 * globally == 1, substitutes all occurrences of what, otherwise only the
516 * first one 516 * first one
517 */ 517 */
518static char * 518static char *
519_rl_compat_sub(const char *str, const char *what, const char *with, 519_rl_compat_sub(const char *str, const char *what, const char *with,
520 int globally) 520 int globally)
521{ 521{
522 const char *s; 522 const char *s;
523 char *r, *result; 523 char *r, *result;
524 size_t len, with_len, what_len; 524 size_t len, with_len, what_len;
525 525
526 len = strlen(str); 526 len = strlen(str);
527 with_len = strlen(with); 527 with_len = strlen(with);
528 what_len = strlen(what); 528 what_len = strlen(what);
529 529
530 /* calculate length we need for result */ 530 /* calculate length we need for result */
531 s = str; 531 s = str;
532 while (*s) { 532 while (*s) {
533 if (*s == *what && !strncmp(s, what, what_len)) { 533 if (*s == *what && !strncmp(s, what, what_len)) {
534 len += with_len - what_len; 534 len += with_len - what_len;
535 if (!globally) 535 if (!globally)
536 break; 536 break;
537 s += what_len; 537 s += what_len;
538 } else 538 } else
539 s++; 539 s++;
540 } 540 }
541 r = result = el_calloc(len + 1, sizeof(*r)); 541 r = result = el_calloc(len + 1, sizeof(*r));
542 if (result == NULL) 542 if (result == NULL)
543 return NULL; 543 return NULL;
544 s = str; 544 s = str;
545 while (*s) { 545 while (*s) {
546 if (*s == *what && !strncmp(s, what, what_len)) { 546 if (*s == *what && !strncmp(s, what, what_len)) {
547 memcpy(r, with, with_len); 547 memcpy(r, with, with_len);
548 r += with_len; 548 r += with_len;
549 s += what_len; 549 s += what_len;
550 if (!globally) { 550 if (!globally) {
551 (void)strcpy(r, s); 551 (void)strcpy(r, s);
552 return result; 552 return result;
553 } 553 }
554 } else 554 } else
555 *r++ = *s++; 555 *r++ = *s++;
556 } 556 }
557 *r = '\0'; 557 *r = '\0';
558 return result; 558 return result;
559} 559}
560 560
561static char *last_search_pat; /* last !?pat[?] search pattern */ 561static char *last_search_pat; /* last !?pat[?] search pattern */
562static char *last_search_match; /* last !?pat[?] that matched */ 562static char *last_search_match; /* last !?pat[?] that matched */
563 563
564const char * 564const char *
565get_history_event(const char *cmd, int *cindex, int qchar) 565get_history_event(const char *cmd, int *cindex, int qchar)
566{ 566{
567 int idx, sign, sub, num, begin, ret; 567 int idx, sign, sub, num, begin, ret;
568 size_t len; 568 size_t len;
569 char *pat; 569 char *pat;
570 const char *rptr; 570 const char *rptr;
571 HistEvent ev; 571 HistEvent ev;
572 572
573 idx = *cindex; 573 idx = *cindex;
574 if (cmd[idx++] != history_expansion_char) 574 if (cmd[idx++] != history_expansion_char)
575 return NULL; 575 return NULL;
576 576
577 /* find out which event to take */ 577 /* find out which event to take */
578 if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { 578 if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
579 if (history(h, &ev, H_FIRST) != 0) 579 if (history(h, &ev, H_FIRST) != 0)
580 return NULL; 580 return NULL;
581 *cindex = cmd[idx]? (idx + 1):idx; 581 *cindex = cmd[idx]? (idx + 1):idx;
582 return ev.str; 582 return ev.str;
583 } 583 }
584 sign = 0; 584 sign = 0;
585 if (cmd[idx] == '-') { 585 if (cmd[idx] == '-') {
586 sign = 1; 586 sign = 1;
587 idx++; 587 idx++;
588 } 588 }
589 589
590 if ('0' <= cmd[idx] && cmd[idx] <= '9') { 590 if ('0' <= cmd[idx] && cmd[idx] <= '9') {
591 HIST_ENTRY *he; 591 HIST_ENTRY *he;
592 592
593 num = 0; 593 num = 0;
594 while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') { 594 while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
595 num = num * 10 + cmd[idx] - '0'; 595 num = num * 10 + cmd[idx] - '0';
596 idx++; 596 idx++;
597 } 597 }
598 if (sign) 598 if (sign)
599 num = history_length - num + history_base; 599 num = history_length - num + history_base;
600 600
601 if (!(he = history_get(num))) 601 if (!(he = history_get(num)))
602 return NULL; 602 return NULL;
603 603
604 *cindex = idx; 604 *cindex = idx;
605 return he->line; 605 return he->line;
606 } 606 }
607 sub = 0; 607 sub = 0;
608 if (cmd[idx] == '?') { 608 if (cmd[idx] == '?') {
609 sub = 1; 609 sub = 1;
610 idx++; 610 idx++;
611 } 611 }
612 begin = idx; 612 begin = idx;
613 while (cmd[idx]) { 613 while (cmd[idx]) {
614 if (cmd[idx] == '\n') 614 if (cmd[idx] == '\n')
615 break; 615 break;
616 if (sub && cmd[idx] == '?') 616 if (sub && cmd[idx] == '?')
617 break; 617 break;
618 if (!sub && (cmd[idx] == ':' || cmd[idx] == ' ' 618 if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
619 || cmd[idx] == '\t' || cmd[idx] == qchar)) 619 || cmd[idx] == '\t' || cmd[idx] == qchar))
620 break; 620 break;
621 idx++; 621 idx++;
622 } 622 }
623 len = (size_t)idx - (size_t)begin; 623 len = (size_t)idx - (size_t)begin;
624 if (sub && cmd[idx] == '?') 624 if (sub && cmd[idx] == '?')
625 idx++; 625 idx++;
626 if (sub && len == 0 && last_search_pat && *last_search_pat) 626 if (sub && len == 0 && last_search_pat && *last_search_pat)
627 pat = last_search_pat; 627 pat = last_search_pat;
628 else if (len == 0) 628 else if (len == 0)
629 return NULL; 629 return NULL;
630 else { 630 else {
631 if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL) 631 if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL)
632 return NULL; 632 return NULL;
633 (void)strlcpy(pat, cmd + begin, len + 1); 633 (void)strlcpy(pat, cmd + begin, len + 1);
634 } 634 }
635 635
636 if (history(h, &ev, H_CURR) != 0) { 636 if (history(h, &ev, H_CURR) != 0) {
637 if (pat != last_search_pat) 637 if (pat != last_search_pat)
638 el_free(pat); 638 el_free(pat);
639 return NULL; 639 return NULL;
640 } 640 }
641 num = ev.num; 641 num = ev.num;
642 642
643 if (sub) { 643 if (sub) {
644 if (pat != last_search_pat) { 644 if (pat != last_search_pat) {
645 el_free(last_search_pat); 645 el_free(last_search_pat);
646 last_search_pat = pat; 646 last_search_pat = pat;
647 } 647 }
648 ret = history_search(pat, -1); 648 ret = history_search(pat, -1);
649 } else 649 } else
650 ret = history_search_prefix(pat, -1); 650 ret = history_search_prefix(pat, -1);
651 651
652 if (ret == -1) { 652 if (ret == -1) {
653 /* restore to end of list on failed search */ 653 /* restore to end of list on failed search */
654 history(h, &ev, H_FIRST); 654 history(h, &ev, H_FIRST);
655 (void)fprintf(rl_outstream, "%s: Event not found\n", pat); 655 (void)fprintf(rl_outstream, "%s: Event not found\n", pat);
656 if (pat != last_search_pat) 656 if (pat != last_search_pat)
657 el_free(pat); 657 el_free(pat);
658 return NULL; 658 return NULL;
659 } 659 }
660 660
661 if (sub && len) { 661 if (sub && len) {
662 el_free(last_search_match); 662 el_free(last_search_match);
663 last_search_match = strdup(pat); 663 last_search_match = strdup(pat);
664 } 664 }
665 665
666 if (pat != last_search_pat) 666 if (pat != last_search_pat)
667 el_free(pat); 667 el_free(pat);
668 668
669 if (history(h, &ev, H_CURR) != 0) 669 if (history(h, &ev, H_CURR) != 0)
670 return NULL; 670 return NULL;
671 *cindex = idx; 671 *cindex = idx;
672 rptr = ev.str; 672 rptr = ev.str;
673 673
674 /* roll back to original position */ 674 /* roll back to original position */
675 (void)history(h, &ev, H_SET, num); 675 (void)history(h, &ev, H_SET, num);
676 676
677 return rptr; 677 return rptr;
678} 678}
679 679
680static int 680static int
681getfrom(const char **cmdp, char **fromp, const char *search, int delim) 681getfrom(const char **cmdp, char **fromp, const char *search, int delim)
682{ 682{
683 size_t size = 16; 683 size_t size = 16;
684 size_t len = 0; 684 size_t len = 0;
685 const char *cmd = *cmdp; 685 const char *cmd = *cmdp;
686 char *what = el_realloc(*fromp, size * sizeof(*what)); 686 char *what = el_realloc(*fromp, size * sizeof(*what));
687 if (what == NULL){ 687 if (what == NULL){
688 el_free(*fromp); 688 el_free(*fromp);
689 *fromp = NULL; 689 *fromp = NULL;
690 return 0; 690 return 0;
691 } 691 }
692 for (; *cmd && *cmd != delim; cmd++) { 692 for (; *cmd && *cmd != delim; cmd++) {
693 if (*cmd == '\\' && cmd[1] == delim) 693 if (*cmd == '\\' && cmd[1] == delim)
694 cmd++; 694 cmd++;
695 if (len - 1 >= size) { 695 if (len - 1 >= size) {
696 char *nwhat; 696 char *nwhat;
697 nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat)); 697 nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat));
698 if (nwhat == NULL) { 698 if (nwhat == NULL) {
699 el_free(what); 699 el_free(what);
700 el_free(*fromp); 700 el_free(*fromp);
701 *cmdp = cmd; 701 *cmdp = cmd;
702 *fromp = NULL; 702 *fromp = NULL;
703 return 0; 703 return 0;
704 } 704 }
705 what = nwhat; 705 what = nwhat;
706 } 706 }
707 what[len++] = *cmd; 707 what[len++] = *cmd;
708 } 708 }
709 what[len] = '\0'; 709 what[len] = '\0';
710 *fromp = what; 710 *fromp = what;
711 *cmdp = cmd; 711 *cmdp = cmd;
712 if (*what == '\0') { 712 if (*what == '\0') {
713 el_free(what); 713 el_free(what);
714 if (search) { 714 if (search) {
715 *fromp = strdup(search); 715 *fromp = strdup(search);
716 if (*fromp == NULL) { 716 if (*fromp == NULL) {
717 return 0; 717 return 0;
718 } 718 }
719 } else { 719 } else {
720 *fromp = NULL; 720 *fromp = NULL;
721 return -1; 721 return -1;
722 } 722 }
723 } 723 }
724 if (!*cmd) { 724 if (!*cmd) {
725 el_free(what); 725 el_free(what);
726 *fromp = NULL; 726 *fromp = NULL;
727 return -1; 727 return -1;
728 } 728 }
729 729
730 cmd++; /* shift after delim */ 730 cmd++; /* shift after delim */
731 *cmdp = cmd; 731 *cmdp = cmd;
732 732
733 if (!*cmd) { 733 if (!*cmd) {
734 el_free(what); 734 el_free(what);
735 *fromp = NULL; 735 *fromp = NULL;
736 return -1; 736 return -1;
737 } 737 }
738 return 1; 738 return 1;
739} 739}
740 740
741static int 741static int
742getto(const char **cmdp, char **top, const char *from, int delim) 742getto(const char **cmdp, char **top, const char *from, int delim)
743{ 743{
744 size_t size = 16; 744 size_t size = 16;
745 size_t len = 0; 745 size_t len = 0;
746 size_t from_len = strlen(from); 746 size_t from_len = strlen(from);
747 const char *cmd = *cmdp; 747 const char *cmd = *cmdp;
748 char *with = el_realloc(*top, size * sizeof(*with)); 748 char *with = el_realloc(*top, size * sizeof(*with));
749 *top = NULL; 749 *top = NULL;
750 if (with == NULL) 750 if (with == NULL)
751 goto out; 751 goto out;
752 752
753 for (; *cmd && *cmd != delim; cmd++) { 753 for (; *cmd && *cmd != delim; cmd++) {
754 if (len + from_len + 1 >= size) { 754 if (len + from_len + 1 >= size) {
755 char *nwith; 755 char *nwith;
756 size += from_len + 1; 756 size += from_len + 1;
757 nwith = el_realloc(with, size * sizeof(*nwith)); 757 nwith = el_realloc(with, size * sizeof(*nwith));
758 if (nwith == NULL) 758 if (nwith == NULL)
759 goto out; 759 goto out;
760 with = nwith; 760 with = nwith;
761 } 761 }
762 if (*cmd == '&') { 762 if (*cmd == '&') {
763 /* safe */ 763 /* safe */
764 strcpy(&with[len], from); 764 strcpy(&with[len], from);
765 len += from_len; 765 len += from_len;
766 continue; 766 continue;
767 } 767 }
768 if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&')) 768 if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&'))
769 cmd++; 769 cmd++;
770 with[len++] = *cmd; 770 with[len++] = *cmd;
771 } 771 }
772 if (!*cmd) 772 if (!*cmd)
773 goto out; 773 goto out;
774 with[len] = '\0'; 774 with[len] = '\0';
775 *top = with; 775 *top = with;
776 *cmdp = cmd; 776 *cmdp = cmd;
777 return 1; 777 return 1;
778out: 778out:
779 el_free(with); 779 el_free(with);
780 el_free(*top); 780 el_free(*top);
781 *top = NULL; 781 *top = NULL;
782 *cmdp = cmd; 782 *cmdp = cmd;
783 return -1; 783 return -1;
784} 784}
785 785
786static void 786static void
787replace(char **tmp, int c) 787replace(char **tmp, int c)
788{ 788{
789 char *aptr; 789 char *aptr;
790 if ((aptr = strrchr(*tmp, c)) == NULL) 790 if ((aptr = strrchr(*tmp, c)) == NULL)
791 return; 791 return;
792 aptr = strdup(aptr + 1); // XXX: check 792 aptr = strdup(aptr + 1); // XXX: check
793 el_free(*tmp); 793 el_free(*tmp);
794 *tmp = aptr; 794 *tmp = aptr;
795} 795}
796 796
797/* 797/*
798 * the real function doing history expansion - takes as argument command 798 * the real function doing history expansion - takes as argument command
799 * to do and data upon which the command should be executed 799 * to do and data upon which the command should be executed
800 * does expansion the way I've understood readline documentation 800 * does expansion the way I've understood readline documentation
801 * 801 *
802 * returns 0 if data was not modified, 1 if it was and 2 if the string 802 * returns 0 if data was not modified, 1 if it was and 2 if the string
803 * should be only printed and not executed; in case of error, 803 * should be only printed and not executed; in case of error,
804 * returns -1 and *result points to NULL 804 * returns -1 and *result points to NULL
805 * it's the caller's responsibility to free() the string returned in *result 805 * it's the caller's responsibility to free() the string returned in *result
806 */ 806 */
807static int 807static int
808_history_expand_command(const char *command, size_t offs, size_t cmdlen, 808_history_expand_command(const char *command, size_t offs, size_t cmdlen,
809 char **result) 809 char **result)
810{ 810{
811 char *tmp, *search = NULL, *aptr, delim; 811 char *tmp, *search = NULL, *aptr, delim;
812 const char *ptr, *cmd; 812 const char *ptr, *cmd;
813 static char *from = NULL, *to = NULL; 813 static char *from = NULL, *to = NULL;
814 int start, end, idx, has_mods = 0; 814 int start, end, idx, has_mods = 0;
815 int p_on = 0, g_on = 0, ev; 815 int p_on = 0, g_on = 0, ev;
816 816
817 *result = NULL; 817 *result = NULL;
818 aptr = NULL; 818 aptr = NULL;
819 ptr = NULL; 819 ptr = NULL;
820 820
821 /* First get event specifier */ 821 /* First get event specifier */
822 idx = 0; 822 idx = 0;
823 823
824 if (strchr(":^*$", command[offs + 1])) { 824 if (strchr(":^*$", command[offs + 1])) {
825 char str[4]; 825 char str[4];
826 /* 826 /*
827 * "!:" is shorthand for "!!:". 827 * "!:" is shorthand for "!!:".
828 * "!^", "!*" and "!$" are shorthand for 828 * "!^", "!*" and "!$" are shorthand for
829 * "!!:^", "!!:*" and "!!:$" respectively. 829 * "!!:^", "!!:*" and "!!:$" respectively.
830 */ 830 */
831 str[0] = str[1] = '!'; 831 str[0] = str[1] = '!';
832 str[2] = '0'; 832 str[2] = '0';
833 ptr = get_history_event(str, &idx, 0); 833 ptr = get_history_event(str, &idx, 0);
834 idx = (command[offs + 1] == ':')? 1:0; 834 idx = (command[offs + 1] == ':')? 1:0;
835 has_mods = 1; 835 has_mods = 1;
836 } else { 836 } else {
837 if (command[offs + 1] == '#') { 837 if (command[offs + 1] == '#') {
838 /* use command so far */ 838 /* use command so far */
839 if ((aptr = el_calloc(offs + 1, sizeof(*aptr))) 839 if ((aptr = el_calloc(offs + 1, sizeof(*aptr)))
840 == NULL) 840 == NULL)
841 return -1; 841 return -1;
842 (void)strlcpy(aptr, command, offs + 1); 842 (void)strlcpy(aptr, command, offs + 1);
843 idx = 1; 843 idx = 1;
844 } else { 844 } else {
845 int qchar; 845 int qchar;
846 846
847 qchar = (offs > 0 && command[offs - 1] == '"') 847 qchar = (offs > 0 && command[offs - 1] == '"')
848 ? '"' : '\0'; 848 ? '"' : '\0';
849 ptr = get_history_event(command + offs, &idx, qchar); 849 ptr = get_history_event(command + offs, &idx, qchar);
850 } 850 }
851 has_mods = command[offs + (size_t)idx] == ':'; 851 has_mods = command[offs + (size_t)idx] == ':';
852 } 852 }
853 853
854 if (ptr == NULL && aptr == NULL) 854 if (ptr == NULL && aptr == NULL)
855 return -1; 855 return -1;
856 856
857 if (!has_mods) { 857 if (!has_mods) {
858 *result = strdup(aptr ? aptr : ptr); 858 *result = strdup(aptr ? aptr : ptr);
859 if (aptr) 859 if (aptr)
860 el_free(aptr); 860 el_free(aptr);
861 if (*result == NULL) 861 if (*result == NULL)
862 return -1; 862 return -1;
863 return 1; 863 return 1;
864 } 864 }
865 865
866 cmd = command + offs + idx + 1; 866 cmd = command + offs + idx + 1;
867 867
868 /* Now parse any word designators */ 868 /* Now parse any word designators */
869 869
870 if (*cmd == '%') /* last word matched by ?pat? */ 870 if (*cmd == '%') /* last word matched by ?pat? */
871 tmp = strdup(last_search_match ? last_search_match : ""); 871 tmp = strdup(last_search_match ? last_search_match : "");
872 else if (strchr("^*$-0123456789", *cmd)) { 872 else if (strchr("^*$-0123456789", *cmd)) {
873 start = end = -1; 873 start = end = -1;
874 if (*cmd == '^') 874 if (*cmd == '^')
875 start = end = 1, cmd++; 875 start = end = 1, cmd++;
876 else if (*cmd == '$') 876 else if (*cmd == '$')
877 start = -1, cmd++; 877 start = -1, cmd++;
878 else if (*cmd == '*') 878 else if (*cmd == '*')
879 start = 1, cmd++; 879 start = 1, cmd++;
880 else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { 880 else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
881 start = 0; 881 start = 0;
882 while (*cmd && '0' <= *cmd && *cmd <= '9') 882 while (*cmd && '0' <= *cmd && *cmd <= '9')
883 start = start * 10 + *cmd++ - '0'; 883 start = start * 10 + *cmd++ - '0';
884 884
885 if (*cmd == '-') { 885 if (*cmd == '-') {
886 if (isdigit((unsigned char) cmd[1])) { 886 if (isdigit((unsigned char) cmd[1])) {
887 cmd++; 887 cmd++;
888 end = 0; 888 end = 0;
889 while (*cmd && '0' <= *cmd && *cmd <= '9') 889 while (*cmd && '0' <= *cmd && *cmd <= '9')
890 end = end * 10 + *cmd++ - '0'; 890 end = end * 10 + *cmd++ - '0';
891 } else if (cmd[1] == '$') { 891 } else if (cmd[1] == '$') {
892 cmd += 2; 892 cmd += 2;
893 end = -1; 893 end = -1;
894 } else { 894 } else {
895 cmd++; 895 cmd++;
896 end = -2; 896 end = -2;
897 } 897 }
898 } else if (*cmd == '*') 898 } else if (*cmd == '*')
899 end = -1, cmd++; 899 end = -1, cmd++;
900 else 900 else
901 end = start; 901 end = start;
902 } 902 }
903 tmp = history_arg_extract(start, end, aptr? aptr:ptr); 903 tmp = history_arg_extract(start, end, aptr? aptr:ptr);
904 if (tmp == NULL) { 904 if (tmp == NULL) {
905 (void)fprintf(rl_outstream, "%s: Bad word specifier", 905 (void)fprintf(rl_outstream, "%s: Bad word specifier",
906 command + offs + idx); 906 command + offs + idx);
907 if (aptr) 907 if (aptr)
908 el_free(aptr); 908 el_free(aptr);
909 return -1; 909 return -1;
910 } 910 }
911 } else 911 } else
912 tmp = strdup(aptr? aptr:ptr); 912 tmp = strdup(aptr? aptr:ptr);
913 913
914 if (aptr) 914 if (aptr)
915 el_free(aptr); 915 el_free(aptr);
916 916
917 if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { 917 if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
918 *result = tmp; 918 *result = tmp;
919 return 1; 919 return 1;
920 } 920 }
921 921
922 for (; *cmd; cmd++) { 922 for (; *cmd; cmd++) {
923 switch (*cmd) { 923 switch (*cmd) {
924 case ':': 924 case ':':
925 continue; 925 continue;
926 case 'h': /* remove trailing path */ 926 case 'h': /* remove trailing path */
927 if ((aptr = strrchr(tmp, '/')) != NULL) 927 if ((aptr = strrchr(tmp, '/')) != NULL)
928 *aptr = '\0'; 928 *aptr = '\0';
929 continue; 929 continue;
930 case 't': /* remove leading path */ 930 case 't': /* remove leading path */
931 replace(&tmp, '/'); 931 replace(&tmp, '/');
932 continue; 932 continue;
933 case 'r': /* remove trailing suffix */ 933 case 'r': /* remove trailing suffix */
934 if ((aptr = strrchr(tmp, '.')) != NULL) 934 if ((aptr = strrchr(tmp, '.')) != NULL)
935 *aptr = '\0'; 935 *aptr = '\0';
936 continue; 936 continue;
937 case 'e': /* remove all but suffix */ 937 case 'e': /* remove all but suffix */
938 replace(&tmp, '.'); 938 replace(&tmp, '.');
939 continue; 939 continue;
940 case 'p': /* print only */ 940 case 'p': /* print only */
941 p_on = 1; 941 p_on = 1;
942 continue; 942 continue;
943 case 'g': 943 case 'g':
944 g_on = 2; 944 g_on = 2;
945 continue; 945 continue;
946 case '&': 946 case '&':
947 if (from == NULL || to == NULL) 947 if (from == NULL || to == NULL)
948 continue; 948 continue;
949 /*FALLTHROUGH*/ 949 /*FALLTHROUGH*/
950 case 's': 950 case 's':
951 ev = -1; 951 ev = -1;
952 delim = *++cmd; 952 delim = *++cmd;
953 if (delim == '\0' || *++cmd == '\0') 953 if (delim == '\0' || *++cmd == '\0')
954 goto out; 954 goto out;
955 if ((ev = getfrom(&cmd, &from, search, delim)) != 1) 955 if ((ev = getfrom(&cmd, &from, search, delim)) != 1)
956 goto out; 956 goto out;
957 if ((ev = getto(&cmd, &to, from, delim)) != 1) 957 if ((ev = getto(&cmd, &to, from, delim)) != 1)
958 goto out; 958 goto out;
959 aptr = _rl_compat_sub(tmp, from, to, g_on); 959 aptr = _rl_compat_sub(tmp, from, to, g_on);
960 if (aptr) { 960 if (aptr) {
961 el_free(tmp); 961 el_free(tmp);
962 tmp = aptr; 962 tmp = aptr;
963 } 963 }
964 g_on = 0; 964 g_on = 0;
965 cmd--; 965 cmd--;
966 continue; 966 continue;
967 } 967 }
968 } 968 }
969 *result = tmp; 969 *result = tmp;
970 return p_on ? 2 : 1; 970 return p_on ? 2 : 1;
971out: 971out:
972 el_free(tmp); 972 el_free(tmp);
973 return ev; 973 return ev;
974  974
975} 975}
976 976
977 977
978/* 978/*
979 * csh-style history expansion 979 * csh-style history expansion
980 */ 980 */
981int 981int
982history_expand(char *str, char **output) 982history_expand(char *str, char **output)
983{ 983{
984 int ret = 0; 984 int ret = 0;
985 size_t idx, i, size; 985 size_t idx, i, size;
986 char *tmp, *result; 986 char *tmp, *result;
987 987
988 if (h == NULL || e == NULL) 988 if (h == NULL || e == NULL)
989 rl_initialize(); 989 rl_initialize();
990 990
991 if (history_expansion_char == 0) { 991 if (history_expansion_char == 0) {
992 *output = strdup(str); 992 *output = strdup(str);
993 return 0; 993 return 0;
994 } 994 }
995 995
996 *output = NULL; 996 *output = NULL;
997 if (str[0] == history_subst_char) { 997 if (str[0] == history_subst_char) {
998 /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ 998 /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
999 *output = el_calloc(strlen(str) + 4 + 1, sizeof(**output)); 999 *output = el_calloc(strlen(str) + 4 + 1, sizeof(**output));
1000 if (*output == NULL) 1000 if (*output == NULL)
1001 return 0; 1001 return 0;
1002 (*output)[0] = (*output)[1] = history_expansion_char; 1002 (*output)[0] = (*output)[1] = history_expansion_char;
1003 (*output)[2] = ':'; 1003 (*output)[2] = ':';
1004 (*output)[3] = 's'; 1004 (*output)[3] = 's';
1005 (void)strcpy((*output) + 4, str); 1005 (void)strcpy((*output) + 4, str);
1006 str = *output; 1006 str = *output;
1007 } else { 1007 } else {
1008 *output = strdup(str); 1008 *output = strdup(str);
1009 if (*output == NULL) 1009 if (*output == NULL)
1010 return 0; 1010 return 0;
1011 } 1011 }
1012 1012
1013#define ADD_STRING(what, len, fr) \ 1013#define ADD_STRING(what, len, fr) \
1014 { \ 1014 { \
1015 if (idx + len + 1 > size) { \ 1015 if (idx + len + 1 > size) { \
1016 char *nresult = el_realloc(result, \ 1016 char *nresult = el_realloc(result, \
1017 (size += len + 1) * sizeof(*nresult)); \ 1017 (size += len + 1) * sizeof(*nresult)); \
1018 if (nresult == NULL) { \ 1018 if (nresult == NULL) { \
1019 el_free(*output); \ 1019 el_free(*output); \
1020 el_free(fr); \ 1020 el_free(fr); \
1021 return 0; \ 1021 return 0; \
1022 } \ 1022 } \
1023 result = nresult; \ 1023 result = nresult; \
1024 } \ 1024 } \
1025 (void)strlcpy(&result[idx], what, len + 1); \ 1025 (void)strlcpy(&result[idx], what, len + 1); \
1026 idx += len; \ 1026 idx += len; \
1027 } 1027 }
1028 1028
1029 result = NULL; 1029 result = NULL;
1030 size = idx = 0; 1030 size = idx = 0;
1031 tmp = NULL; 1031 tmp = NULL;
1032 for (i = 0; str[i];) { 1032 for (i = 0; str[i];) {
1033 int qchar, loop_again; 1033 int qchar, loop_again;
1034 size_t len, start, j; 1034 size_t len, start, j;
1035 1035
1036 qchar = 0; 1036 qchar = 0;
1037 loop_again = 1; 1037 loop_again = 1;
1038 start = j = i; 1038 start = j = i;
1039loop: 1039loop:
1040 for (; str[j]; j++) { 1040 for (; str[j]; j++) {
1041 if (str[j] == '\\' && 1041 if (str[j] == '\\' &&
1042 str[j + 1] == history_expansion_char) { 1042 str[j + 1] == history_expansion_char) {
1043 len = strlen(&str[j + 1]) + 1; 1043 len = strlen(&str[j + 1]) + 1;
1044 memmove(&str[j], &str[j + 1], len); 1044 memmove(&str[j], &str[j + 1], len);
1045 continue; 1045 continue;
1046 } 1046 }
1047 if (!loop_again) { 1047 if (!loop_again) {
1048 if (isspace((unsigned char) str[j]) 1048 if (isspace((unsigned char) str[j])
1049 || str[j] == qchar) 1049 || str[j] == qchar)
1050 break; 1050 break;
1051 } 1051 }
1052 if (str[j] == history_expansion_char 1052 if (str[j] == history_expansion_char
1053 && !strchr(history_no_expand_chars, str[j + 1]) 1053 && !strchr(history_no_expand_chars, str[j + 1])
1054 && (!history_inhibit_expansion_function || 1054 && (!history_inhibit_expansion_function ||
1055 (*history_inhibit_expansion_function)(str, 1055 (*history_inhibit_expansion_function)(str,
1056 (int)j) == 0)) 1056 (int)j) == 0))
1057 break; 1057 break;
1058 } 1058 }
1059 1059
1060 if (str[j] && loop_again) { 1060 if (str[j] && loop_again) {
1061 i = j; 1061 i = j;
1062 qchar = (j > 0 && str[j - 1] == '"' )? '"':0; 1062 qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
1063 j++; 1063 j++;
1064 if (str[j] == history_expansion_char) 1064 if (str[j] == history_expansion_char)
1065 j++; 1065 j++;
1066 loop_again = 0; 1066 loop_again = 0;
1067 goto loop; 1067 goto loop;
1068 } 1068 }
1069 len = i - start; 1069 len = i - start;
1070 ADD_STRING(&str[start], len, NULL); 1070 ADD_STRING(&str[start], len, NULL);
1071 1071
1072 if (str[i] == '\0' || str[i] != history_expansion_char) { 1072 if (str[i] == '\0' || str[i] != history_expansion_char) {
1073 len = j - i; 1073 len = j - i;
1074 ADD_STRING(&str[i], len, NULL); 1074 ADD_STRING(&str[i], len, NULL);
1075 if (start == 0) 1075 if (start == 0)
1076 ret = 0; 1076 ret = 0;
1077 else 1077 else
1078 ret = 1; 1078 ret = 1;
1079 break; 1079 break;
1080 } 1080 }
1081 ret = _history_expand_command (str, i, (j - i), &tmp); 1081 ret = _history_expand_command (str, i, (j - i), &tmp);
1082 if (ret > 0 && tmp) { 1082 if (ret > 0 && tmp) {
1083 len = strlen(tmp); 1083 len = strlen(tmp);
1084 ADD_STRING(tmp, len, tmp); 1084 ADD_STRING(tmp, len, tmp);
1085 } 1085 }
1086 if (tmp) { 1086 if (tmp) {
1087 el_free(tmp); 1087 el_free(tmp);
1088 tmp = NULL; 1088 tmp = NULL;
1089 } 1089 }
1090 i = j; 1090 i = j;
1091 } 1091 }
1092 1092
1093 /* ret is 2 for "print only" option */ 1093 /* ret is 2 for "print only" option */
1094 if (ret == 2) { 1094 if (ret == 2) {
1095 add_history(result); 1095 add_history(result);
1096#ifdef GDB_411_HACK 1096#ifdef GDB_411_HACK
1097 /* gdb 4.11 has been shipped with readline, where */ 1097 /* gdb 4.11 has been shipped with readline, where */
1098 /* history_expand() returned -1 when the line */ 1098 /* history_expand() returned -1 when the line */
1099 /* should not be executed; in readline 2.1+ */ 1099 /* should not be executed; in readline 2.1+ */
1100 /* it should return 2 in such a case */ 1100 /* it should return 2 in such a case */
1101 ret = -1; 1101 ret = -1;
1102#endif 1102#endif
1103 } 1103 }
1104 el_free(*output); 1104 el_free(*output);
1105 *output = result; 1105 *output = result;
1106 1106
1107 return ret; 1107 return ret;
1108} 1108}
1109 1109
1110/* 1110/*
1111* Return a string consisting of arguments of "str" from "start" to "end". 1111* Return a string consisting of arguments of "str" from "start" to "end".
1112*/ 1112*/
1113char * 1113char *
1114history_arg_extract(int start, int end, const char *str) 1114history_arg_extract(int start, int end, const char *str)
1115{ 1115{
1116 size_t i, len, max; 1116 size_t i, len, max;
1117 char **arr, *result = NULL; 1117 char **arr, *result = NULL;
1118 1118
1119 arr = history_tokenize(str); 1119 arr = history_tokenize(str);
1120 if (!arr) 1120 if (!arr)
1121 return NULL; 1121 return NULL;
1122 if (arr && *arr == NULL) 1122 if (arr && *arr == NULL)
1123 goto out; 1123 goto out;
1124 1124
1125 for (max = 0; arr[max]; max++) 1125 for (max = 0; arr[max]; max++)
1126 continue; 1126 continue;
1127 max--; 1127 max--;
1128 1128
1129 if (start == '$') 1129 if (start == '$')
1130 start = (int)max; 1130 start = (int)max;
1131 if (end == '$') 1131 if (end == '$')
1132 end = (int)max; 1132 end = (int)max;
1133 if (end < 0) 1133 if (end < 0)
1134 end = (int)max + end + 1; 1134 end = (int)max + end + 1;
1135 if (start < 0) 1135 if (start < 0)
1136 start = end; 1136 start = end;
1137 1137
1138 if (start < 0 || end < 0 || (size_t)start > max || 1138 if (start < 0 || end < 0 || (size_t)start > max ||
1139 (size_t)end > max || start > end) 1139 (size_t)end > max || start > end)
1140 goto out; 1140 goto out;
1141 1141
1142 for (i = (size_t)start, len = 0; i <= (size_t)end; i++) 1142 for (i = (size_t)start, len = 0; i <= (size_t)end; i++)
1143 len += strlen(arr[i]) + 1; 1143 len += strlen(arr[i]) + 1;
1144 len++; 1144 len++;
1145 result = el_calloc(len, sizeof(*result)); 1145 result = el_calloc(len, sizeof(*result));
1146 if (result == NULL) 1146 if (result == NULL)
1147 goto out; 1147 goto out;
1148 1148
1149 for (i = (size_t)start, len = 0; i <= (size_t)end; i++) { 1149 for (i = (size_t)start, len = 0; i <= (size_t)end; i++) {
1150 (void)strcpy(result + len, arr[i]); 1150 (void)strcpy(result + len, arr[i]);
1151 len += strlen(arr[i]); 1151 len += strlen(arr[i]);
1152 if (i < (size_t)end) 1152 if (i < (size_t)end)
1153 result[len++] = ' '; 1153 result[len++] = ' ';
1154 } 1154 }
1155 result[len] = '\0'; 1155 result[len] = '\0';
1156 1156
1157out: 1157out:
1158 for (i = 0; arr[i]; i++) 1158 for (i = 0; arr[i]; i++)
1159 el_free(arr[i]); 1159 el_free(arr[i]);
1160 el_free(arr); 1160 el_free(arr);
1161 1161
1162 return result; 1162 return result;
1163} 1163}
1164 1164
1165/* 1165/*
1166 * Parse the string into individual tokens, 1166 * Parse the string into individual tokens,
1167 * similar to how shell would do it. 1167 * similar to how shell would do it.
1168 */ 1168 */
1169char ** 1169char **
1170history_tokenize(const char *str) 1170history_tokenize(const char *str)
1171{ 1171{
1172 int size = 1, idx = 0, i, start; 1172 int size = 1, idx = 0, i, start;
1173 size_t len; 1173 size_t len;
1174 char **result = NULL, *temp, delim = '\0'; 1174 char **result = NULL, *temp, delim = '\0';
1175 1175
1176 for (i = 0; str[i];) { 1176 for (i = 0; str[i];) {
1177 while (isspace((unsigned char) str[i])) 1177 while (isspace((unsigned char) str[i]))
1178 i++; 1178 i++;
1179 start = i; 1179 start = i;
1180 for (; str[i];) { 1180 for (; str[i];) {
1181 if (str[i] == '\\') { 1181 if (str[i] == '\\') {
1182 if (str[i+1] != '\0') 1182 if (str[i+1] != '\0')
1183 i++; 1183 i++;
1184 } else if (str[i] == delim) 1184 } else if (str[i] == delim)
1185 delim = '\0'; 1185 delim = '\0';
1186 else if (!delim && 1186 else if (!delim &&
1187 (isspace((unsigned char) str[i]) || 1187 (isspace((unsigned char) str[i]) ||
1188 strchr("()<>;&|$", str[i]))) 1188 strchr("()<>;&|$", str[i])))
1189 break; 1189 break;
1190 else if (!delim && strchr("'`\"", str[i])) 1190 else if (!delim && strchr("'`\"", str[i]))
1191 delim = str[i]; 1191 delim = str[i];
1192 if (str[i]) 1192 if (str[i])
1193 i++; 1193 i++;
1194 } 1194 }
1195 1195
1196 if (idx + 2 >= size) { 1196 if (idx + 2 >= size) {
1197 char **nresult; 1197 char **nresult;
1198 size <<= 1; 1198 size <<= 1;
1199 nresult = el_realloc(result, (size_t)size * sizeof(*nresult)); 1199 nresult = el_realloc(result, (size_t)size * sizeof(*nresult));
1200 if (nresult == NULL) { 1200 if (nresult == NULL) {
1201 el_free(result); 1201 el_free(result);
1202 return NULL; 1202 return NULL;
1203 } 1203 }
1204 result = nresult; 1204 result = nresult;
1205 } 1205 }
1206 len = (size_t)i - (size_t)start; 1206 len = (size_t)i - (size_t)start;
1207 temp = el_calloc(len + 1, sizeof(*temp)); 1207 temp = el_calloc(len + 1, sizeof(*temp));
1208 if (temp == NULL) { 1208 if (temp == NULL) {
1209 for (i = 0; i < idx; i++) 1209 for (i = 0; i < idx; i++)
1210 el_free(result[i]); 1210 el_free(result[i]);
1211 el_free(result); 1211 el_free(result);
1212 return NULL; 1212 return NULL;
1213 } 1213 }
1214 (void)strlcpy(temp, &str[start], len + 1); 1214 (void)strlcpy(temp, &str[start], len + 1);
1215 result[idx++] = temp; 1215 result[idx++] = temp;
1216 result[idx] = NULL; 1216 result[idx] = NULL;
1217 if (str[i]) 1217 if (str[i])
1218 i++; 1218 i++;
1219 } 1219 }
1220 return result; 1220 return result;
1221} 1221}
1222 1222
1223 1223
1224/* 1224/*
1225 * limit size of history record to ``max'' events 1225 * limit size of history record to ``max'' events
1226 */ 1226 */
1227void 1227void
1228stifle_history(int max) 1228stifle_history(int max)
1229{ 1229{
1230 HistEvent ev; 1230 HistEvent ev;
1231 HIST_ENTRY *he; 1231 HIST_ENTRY *he;
1232 1232
1233 if (h == NULL || e == NULL) 1233 if (h == NULL || e == NULL)
1234 rl_initialize(); 1234 rl_initialize();
1235 1235
1236 if (history(h, &ev, H_SETSIZE, max) == 0) { 1236 if (history(h, &ev, H_SETSIZE, max) == 0) {
1237 max_input_history = max; 1237 max_input_history = max;
1238 if (history_length > max) 1238 if (history_length > max)
1239 history_base = history_length - max; 1239 history_base = history_length - max;
1240 while (history_length > max) { 1240 while (history_length > max) {
1241 he = remove_history(0); 1241 he = remove_history(0);
1242 el_free(he->data); 1242 el_free(he->data);
1243 el_free((void *)(unsigned long)he->line); 1243 el_free((void *)(unsigned long)he->line);
1244 el_free(he); 1244 el_free(he);
1245 } 1245 }
1246 } 1246 }
1247} 1247}
1248 1248
1249 1249
1250/* 1250/*
1251 * "unlimit" size of history - set the limit to maximum allowed int value 1251 * "unlimit" size of history - set the limit to maximum allowed int value
1252 */ 1252 */
1253int 1253int
1254unstifle_history(void) 1254unstifle_history(void)
1255{ 1255{
1256 HistEvent ev; 1256 HistEvent ev;
1257 int omax; 1257 int omax;
1258 1258
1259 history(h, &ev, H_SETSIZE, INT_MAX); 1259 history(h, &ev, H_SETSIZE, INT_MAX);
1260 omax = max_input_history; 1260 omax = max_input_history;
1261 max_input_history = INT_MAX; 1261 max_input_history = INT_MAX;
1262 return omax; /* some value _must_ be returned */ 1262 return omax; /* some value _must_ be returned */
1263} 1263}
1264 1264
1265 1265
1266int 1266int
1267history_is_stifled(void) 1267history_is_stifled(void)
1268{ 1268{
1269 1269
1270 /* cannot return true answer */ 1270 /* cannot return true answer */
1271 return max_input_history != INT_MAX; 1271 return max_input_history != INT_MAX;
1272} 1272}
1273 1273
1274static const char _history_tmp_template[] = "/tmp/.historyXXXXXX"; 1274static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
1275 1275
1276int 1276int
1277history_truncate_file (const char *filename, int nlines) 1277history_truncate_file (const char *filename, int nlines)
1278{ 1278{
1279 int ret = 0; 1279 int ret = 0;
1280 FILE *fp, *tp; 1280 FILE *fp, *tp;
1281 char template[sizeof(_history_tmp_template)]; 1281 char template[sizeof(_history_tmp_template)];
1282 char buf[4096]; 1282 char buf[4096];
1283 int fd; 1283 int fd;
1284 char *cp; 1284 char *cp;
1285 off_t off; 1285 off_t off;
1286 int count = 0; 1286 int count = 0;
1287 ssize_t left = 0; 1287 ssize_t left = 0;
1288 1288
1289 if (filename == NULL && (filename = _default_history_file()) == NULL) 1289 if (filename == NULL && (filename = _default_history_file()) == NULL)
1290 return errno; 1290 return errno;
1291 if ((fp = fopen(filename, "r+")) == NULL) 1291 if ((fp = fopen(filename, "r+")) == NULL)
1292 return errno; 1292 return errno;
1293 strcpy(template, _history_tmp_template); 1293 strcpy(template, _history_tmp_template);
1294 if ((fd = mkstemp(template)) == -1) { 1294 if ((fd = mkstemp(template)) == -1) {
1295 ret = errno; 1295 ret = errno;
1296 goto out1; 1296 goto out1;
1297 } 1297 }
1298 1298
1299 if ((tp = fdopen(fd, "r+")) == NULL) { 1299 if ((tp = fdopen(fd, "r+")) == NULL) {
1300 close(fd); 1300 close(fd);
1301 ret = errno; 1301 ret = errno;
1302 goto out2; 1302 goto out2;
1303 } 1303 }
1304 1304
1305 for(;;) { 1305 for(;;) {
1306 if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) { 1306 if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) {
1307 if (ferror(fp)) { 1307 if (ferror(fp)) {
1308 ret = errno; 1308 ret = errno;
1309 break; 1309 break;
1310 } 1310 }
1311 if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) == 1311 if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
1312 (off_t)-1) { 1312 (off_t)-1) {
1313 ret = errno; 1313 ret = errno;
1314 break; 1314 break;
1315 } 1315 }
1316 left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp); 1316 left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp);
1317 if (ferror(fp)) { 1317 if (ferror(fp)) {
1318 ret = errno; 1318 ret = errno;
1319 break; 1319 break;
1320 } 1320 }
1321 if (left == 0) { 1321 if (left == 0) {
1322 count--; 1322 count--;
1323 left = sizeof(buf); 1323 left = sizeof(buf);
1324 } else if (fwrite(buf, (size_t)left, (size_t)1, tp) 1324 } else if (fwrite(buf, (size_t)left, (size_t)1, tp)
1325 != 1) { 1325 != 1) {
1326 ret = errno; 1326 ret = errno;
1327 break; 1327 break;
1328 } 1328 }
1329 fflush(tp); 1329 fflush(tp);
1330 break; 1330 break;
1331 } 1331 }
1332 if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) { 1332 if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) {
1333 ret = errno; 1333 ret = errno;
1334 break; 1334 break;
1335 } 1335 }
1336 count++; 1336 count++;
1337 } 1337 }
1338 if (ret) 1338 if (ret)
1339 goto out3; 1339 goto out3;
1340 cp = buf + left - 1; 1340 cp = buf + left - 1;
1341 if(*cp != '\n') 1341 if(*cp != '\n')
1342 cp++; 1342 cp++;
1343 for(;;) { 1343 for(;;) {
1344 while (--cp >= buf) { 1344 while (--cp >= buf) {
1345 if (*cp == '\n') { 1345 if (*cp == '\n') {
1346 if (--nlines == 0) { 1346 if (--nlines == 0) {
1347 if (++cp >= buf + sizeof(buf)) { 1347 if (++cp >= buf + sizeof(buf)) {
1348 count++; 1348 count++;
1349 cp = buf; 1349 cp = buf;
1350 } 1350 }
1351 break; 1351 break;
1352 } 1352 }
1353 } 1353 }
1354 } 1354 }
1355 if (nlines <= 0 || count == 0) 1355 if (nlines <= 0 || count == 0)
1356 break; 1356 break;
1357 count--; 1357 count--;
1358 if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) { 1358 if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
1359 ret = errno; 1359 ret = errno;
1360 break; 1360 break;
1361 } 1361 }
1362 if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) { 1362 if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) {
1363 if (ferror(tp)) { 1363 if (ferror(tp)) {
1364 ret = errno; 1364 ret = errno;
1365 break; 1365 break;
1366 } 1366 }
1367 ret = EAGAIN; 1367 ret = EAGAIN;
1368 break; 1368 break;
1369 } 1369 }
1370 cp = buf + sizeof(buf); 1370 cp = buf + sizeof(buf);
1371 } 1371 }
1372 1372
1373 if (ret || nlines > 0) 1373 if (ret || nlines > 0)
1374 goto out3; 1374 goto out3;
1375 1375
1376 if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) { 1376 if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
1377 ret = errno; 1377 ret = errno;
1378 goto out3; 1378 goto out3;
1379 } 1379 }
1380 1380
1381 if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) == 1381 if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
1382 (off_t)-1) { 1382 (off_t)-1) {
1383 ret = errno; 1383 ret = errno;
1384 goto out3; 1384 goto out3;
1385 } 1385 }
1386 1386
1387 for(;;) { 1387 for(;;) {
1388 if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) { 1388 if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) {
1389 if (ferror(fp)) 1389 if (ferror(fp))
1390 ret = errno; 1390 ret = errno;
1391 break; 1391 break;
1392 } 1392 }
1393 if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) { 1393 if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) {
1394 ret = errno; 1394 ret = errno;
1395 break; 1395 break;
1396 } 1396 }
1397 } 1397 }
1398 fflush(fp); 1398 fflush(fp);
1399 if((off = ftello(fp)) > 0) 1399 if((off = ftello(fp)) > 0)
1400 (void)ftruncate(fileno(fp), off); 1400 (void)ftruncate(fileno(fp), off);
1401out3: 1401out3:
1402 fclose(tp); 1402 fclose(tp);
1403out2: 1403out2:
1404 unlink(template); 1404 unlink(template);
1405out1: 1405out1:
1406 fclose(fp); 1406 fclose(fp);
1407 1407
1408 return ret; 1408 return ret;
1409} 1409}
1410 1410
1411 1411
1412/* 1412/*
1413 * read history from a file given 1413 * read history from a file given
1414 */ 1414 */
1415int 1415int
1416read_history(const char *filename) 1416read_history(const char *filename)
1417{ 1417{
1418 HistEvent ev; 1418 HistEvent ev;
1419 1419
1420 if (h == NULL || e == NULL) 1420 if (h == NULL || e == NULL)
1421 rl_initialize(); 1421 rl_initialize();
1422 if (filename == NULL && (filename = _default_history_file()) == NULL) 1422 if (filename == NULL && (filename = _default_history_file()) == NULL)
1423 return errno; 1423 return errno;
1424 errno = 0; 1424 errno = 0;
1425 if (history(h, &ev, H_LOAD, filename) == -1) 1425 if (history(h, &ev, H_LOAD, filename) == -1)
1426 return errno ? errno : EINVAL; 1426 return errno ? errno : EINVAL;
1427 if (history(h, &ev, H_GETSIZE) == 0) 1427 if (history(h, &ev, H_GETSIZE) == 0)
1428 history_length = ev.num; 1428 history_length = ev.num;
1429 if (history_length < 0) 1429 if (history_length < 0)
1430 return EINVAL; 1430 return EINVAL;
1431 return 0; 1431 return 0;
1432} 1432}
1433 1433
1434 1434
1435/* 1435/*
1436 * write history to a file given 1436 * write history to a file given
1437 */ 1437 */
1438int 1438int
1439write_history(const char *filename) 1439write_history(const char *filename)
1440{ 1440{
1441 HistEvent ev; 1441 HistEvent ev;
1442 1442
1443 if (h == NULL || e == NULL) 1443 if (h == NULL || e == NULL)
1444 rl_initialize(); 1444 rl_initialize();
1445 if (filename == NULL && (filename = _default_history_file()) == NULL) 1445 if (filename == NULL && (filename = _default_history_file()) == NULL)
1446 return errno; 1446 return errno;
1447 return history(h, &ev, H_SAVE, filename) == -1 ? 1447 return history(h, &ev, H_SAVE, filename) == -1 ?
1448 (errno ? errno : EINVAL) : 0; 1448 (errno ? errno : EINVAL) : 0;
1449} 1449}
1450 1450
1451int 1451int
1452append_history(int n, const char *filename) 1452append_history(int n, const char *filename)
1453{ 1453{
1454 HistEvent ev; 1454 HistEvent ev;
1455 FILE *fp; 1455 FILE *fp;
1456 1456
1457 if (h == NULL || e == NULL) 1457 if (h == NULL || e == NULL)
1458 rl_initialize(); 1458 rl_initialize();
1459 if (filename == NULL && (filename = _default_history_file()) == NULL) 1459 if (filename == NULL && (filename = _default_history_file()) == NULL)
1460 return errno; 1460 return errno;
1461 1461
1462 if ((fp = fopen(filename, "a")) == NULL) 1462 if ((fp = fopen(filename, "a")) == NULL)

cvs diff -r1.52 -r1.53 src/lib/libedit/readline/readline.h (switch to unified diff)

--- src/lib/libedit/readline/readline.h 2022/02/08 15:05:10 1.52
+++ src/lib/libedit/readline/readline.h 2022/02/19 17:45:02 1.53
@@ -1,267 +1,267 @@ @@ -1,267 +1,267 @@
1/* $NetBSD: readline.h,v 1.52 2022/02/08 15:05:10 christos Exp $ */ 1/* $NetBSD: readline.h,v 1.53 2022/02/19 17:45:02 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jaromir Dolecek. 8 * by Jaromir Dolecek.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31#ifndef _READLINE_H_ 31#ifndef _READLINE_H_
32#define _READLINE_H_ 32#define _READLINE_H_
33 33
34#include <sys/types.h> 34#include <sys/types.h>
35#include <stdio.h> 35#include <stdio.h>
36 36
37/* list of readline stuff supported by editline library's readline wrapper */ 37/* list of readline stuff supported by editline library's readline wrapper */
38 38
39/* typedefs */ 39/* typedefs */
40typedef int Function(const char *, int); 40typedef int Function(const char *, int);
41typedef char *CPFunction(const char *, int); 41typedef char *CPFunction(const char *, int);
42typedef void VFunction(void); 42typedef void VFunction(void);
43typedef void rl_vcpfunc_t(char *); 43typedef void rl_vcpfunc_t(char *);
44typedef char **rl_completion_func_t(const char *, int, int); 44typedef char **rl_completion_func_t(const char *, int, int);
45typedef char *rl_compentry_func_t(const char *, int); 45typedef char *rl_compentry_func_t(const char *, int);
46typedef int rl_command_func_t(int, int); 46typedef int rl_command_func_t(int, int);
47typedef int rl_hook_func_t(void); 47typedef int rl_hook_func_t(void);
48typedef int rl_icppfunc_t(char **); 48typedef int rl_icppfunc_t(char **);
49 49
50/* only supports length */ 50/* only supports length */
51typedef struct { 51typedef struct {
52 int length; 52 int length;
53} HISTORY_STATE; 53} HISTORY_STATE;
54 54
55typedef void *histdata_t; 55typedef void *histdata_t;
56 56
57typedef struct _hist_entry { 57typedef struct _hist_entry {
58 const char *line; 58 const char *line;
59 histdata_t data; 59 histdata_t data;
60} HIST_ENTRY; 60} HIST_ENTRY;
61 61
62typedef struct _keymap_entry { 62typedef struct _keymap_entry {
63 char type; 63 char type;
64#define ISFUNC 0 64#define ISFUNC 0
65#define ISKMAP 1 65#define ISKMAP 1
66#define ISMACR 2 66#define ISMACR 2
67 Function *function; 67 Function *function;
68} KEYMAP_ENTRY; 68} KEYMAP_ENTRY;
69 69
70#define KEYMAP_SIZE 256 70#define KEYMAP_SIZE 256
71 71
72typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE]; 72typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE];
73typedef KEYMAP_ENTRY *Keymap; 73typedef KEYMAP_ENTRY *Keymap;
74 74
75#define control_character_threshold 0x20 75#define control_character_threshold 0x20
76#define control_character_bit 0x40 76#define control_character_bit 0x40
77 77
78#ifndef CTRL 78#ifndef CTRL
79#include <sys/ioctl.h> 79#include <sys/ioctl.h>
80#if !defined(__sun) && !defined(__hpux) && !defined(_AIX) 80#if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
81#include <sys/ttydefaults.h> 81#include <sys/ttydefaults.h>
82#endif 82#endif
83#ifndef CTRL 83#ifndef CTRL
84#define CTRL(c) ((c) & 037) 84#define CTRL(c) ((c) & 037)
85#endif 85#endif
86#endif 86#endif
87#ifndef UNCTRL 87#ifndef UNCTRL
88#define UNCTRL(c) (((c) - 'a' + 'A')|control_character_bit) 88#define UNCTRL(c) (((c) - 'a' + 'A')|control_character_bit)
89#endif 89#endif
90 90
91#define RUBOUT 0x7f 91#define RUBOUT 0x7f
92#define ABORT_CHAR CTRL('G') 92#define ABORT_CHAR CTRL('G')
93#define RL_READLINE_VERSION 0x0402 93#define RL_READLINE_VERSION 0x0402
94#define RL_PROMPT_START_IGNORE '\1' 94#define RL_PROMPT_START_IGNORE '\1'
95#define RL_PROMPT_END_IGNORE '\2' 95#define RL_PROMPT_END_IGNORE '\2'
96 96
97#define RL_STATE_NONE 0x000000 97#define RL_STATE_NONE 0x000000
98#define RL_STATE_DONE 0x000001 98#define RL_STATE_DONE 0x000001
99 99
100#define RL_SETSTATE(x) (rl_readline_state |= ((unsigned long) x)) 100#define RL_SETSTATE(x) (rl_readline_state |= ((unsigned long) x))
101#define RL_UNSETSTATE(x) (rl_readline_state &= ~((unsigned long) x)) 101#define RL_UNSETSTATE(x) (rl_readline_state &= ~((unsigned long) x))
102#define RL_ISSTATE(x) (rl_readline_state & ((unsigned long) x)) 102#define RL_ISSTATE(x) (rl_readline_state & ((unsigned long) x))
103 103
104/* global variables used by readline enabled applications */ 104/* global variables used by readline enabled applications */
105#ifdef __cplusplus 105#ifdef __cplusplus
106extern "C" { 106extern "C" {
107#endif 107#endif
108extern const char *rl_library_version; 108extern const char *rl_library_version;
109extern int rl_readline_version; 109extern int rl_readline_version;
110extern const char *rl_readline_name; 110extern const char *rl_readline_name;
111extern FILE *rl_instream; 111extern FILE *rl_instream;
112extern FILE *rl_outstream; 112extern FILE *rl_outstream;
113extern char *rl_line_buffer; 113extern char *rl_line_buffer;
114extern int rl_point, rl_end; 114extern int rl_point, rl_end;
115extern int history_base, history_length; 115extern int history_base, history_length;
116extern int max_input_history; 116extern int max_input_history;
117extern const char *rl_basic_quote_characters; 117extern const char *rl_basic_quote_characters;
118extern const char *rl_basic_word_break_characters; 118extern const char *rl_basic_word_break_characters;
119extern char *rl_completer_word_break_characters; 119extern char *rl_completer_word_break_characters;
120extern const char *rl_completer_quote_characters; 120extern const char *rl_completer_quote_characters;
121extern rl_compentry_func_t *rl_completion_entry_function; 121extern rl_compentry_func_t *rl_completion_entry_function;
122extern char *(*rl_completion_word_break_hook)(void); 122extern char *(*rl_completion_word_break_hook)(void);
123extern rl_completion_func_t *rl_attempted_completion_function; 123extern rl_completion_func_t *rl_attempted_completion_function;
124extern int rl_attempted_completion_over; 124extern int rl_attempted_completion_over;
125extern int rl_completion_type; 125extern int rl_completion_type;
126extern int rl_completion_query_items; 126extern int rl_completion_query_items;
127extern const char *rl_special_prefixes; 127extern const char *rl_special_prefixes;
128extern int rl_completion_append_character; 128extern int rl_completion_append_character;
129extern int rl_inhibit_completion; 129extern int rl_inhibit_completion;
130extern Function *rl_pre_input_hook; 130extern rl_hook_func_t *rl_pre_input_hook;
131extern Function *rl_startup_hook; 131extern rl_hook_func_t *rl_startup_hook;
132extern char *rl_terminal_name; 132extern char *rl_terminal_name;
133extern int rl_already_prompted; 133extern int rl_already_prompted;
134extern char *rl_prompt; 134extern char *rl_prompt;
135extern int rl_done; 135extern int rl_done;
136/* 136/*
137 * The following is not implemented 137 * The following is not implemented
138 */ 138 */
139extern unsigned long rl_readline_state; 139extern unsigned long rl_readline_state;
140extern int rl_catch_signals; 140extern int rl_catch_signals;
141extern int rl_catch_sigwinch; 141extern int rl_catch_sigwinch;
142extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, 142extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
143 emacs_meta_keymap, 143 emacs_meta_keymap,
144 emacs_ctlx_keymap; 144 emacs_ctlx_keymap;
145extern int rl_filename_completion_desired; 145extern int rl_filename_completion_desired;
146extern int rl_ignore_completion_duplicates; 146extern int rl_ignore_completion_duplicates;
147extern int (*rl_getc_function)(FILE *); 147extern int (*rl_getc_function)(FILE *);
148extern VFunction *rl_redisplay_function; 148extern VFunction *rl_redisplay_function;
149extern VFunction *rl_completion_display_matches_hook; 149extern VFunction *rl_completion_display_matches_hook;
150extern VFunction *rl_prep_term_function; 150extern VFunction *rl_prep_term_function;
151extern VFunction *rl_deprep_term_function; 151extern VFunction *rl_deprep_term_function;
152extern rl_hook_func_t *rl_event_hook; 152extern rl_hook_func_t *rl_event_hook;
153extern int readline_echoing_p; 153extern int readline_echoing_p;
154extern int _rl_print_completions_horizontally; 154extern int _rl_print_completions_horizontally;
155extern int _rl_complete_mark_directories; 155extern int _rl_complete_mark_directories;
156extern rl_icppfunc_t *rl_directory_completion_hook; 156extern rl_icppfunc_t *rl_directory_completion_hook;
157extern int rl_completion_suppress_append; 157extern int rl_completion_suppress_append;
158extern int rl_sort_completion_matches; 158extern int rl_sort_completion_matches;
159extern int _rl_completion_prefix_display_length; 159extern int _rl_completion_prefix_display_length;
160extern int _rl_echoing_p; 160extern int _rl_echoing_p;
161extern int history_max_entries; 161extern int history_max_entries;
162extern char *rl_display_prompt; 162extern char *rl_display_prompt;
163extern int rl_erase_empty_line; 163extern int rl_erase_empty_line;
164 164
165/* supported functions */ 165/* supported functions */
166char *readline(const char *); 166char *readline(const char *);
167int rl_initialize(void); 167int rl_initialize(void);
168 168
169void using_history(void); 169void using_history(void);
170int add_history(const char *); 170int add_history(const char *);
171void clear_history(void); 171void clear_history(void);
172int append_history(int, const char *); 172int append_history(int, const char *);
173void stifle_history(int); 173void stifle_history(int);
174int unstifle_history(void); 174int unstifle_history(void);
175int history_is_stifled(void); 175int history_is_stifled(void);
176int where_history(void); 176int where_history(void);
177HIST_ENTRY *current_history(void); 177HIST_ENTRY *current_history(void);
178HIST_ENTRY *history_get(int); 178HIST_ENTRY *history_get(int);
179HIST_ENTRY *remove_history(int); 179HIST_ENTRY *remove_history(int);
180HIST_ENTRY *replace_history_entry(int, const char *, histdata_t); 180HIST_ENTRY *replace_history_entry(int, const char *, histdata_t);
181int history_total_bytes(void); 181int history_total_bytes(void);
182int history_set_pos(int); 182int history_set_pos(int);
183HIST_ENTRY *previous_history(void); 183HIST_ENTRY *previous_history(void);
184HIST_ENTRY *next_history(void); 184HIST_ENTRY *next_history(void);
185HIST_ENTRY **history_list(void); 185HIST_ENTRY **history_list(void);
186int history_search(const char *, int); 186int history_search(const char *, int);
187int history_search_prefix(const char *, int); 187int history_search_prefix(const char *, int);
188int history_search_pos(const char *, int, int); 188int history_search_pos(const char *, int, int);
189int read_history(const char *); 189int read_history(const char *);
190int write_history(const char *); 190int write_history(const char *);
191int history_truncate_file(const char *, int); 191int history_truncate_file(const char *, int);
192int history_expand(char *, char **); 192int history_expand(char *, char **);
193char **history_tokenize(const char *); 193char **history_tokenize(const char *);
194const char *get_history_event(const char *, int *, int); 194const char *get_history_event(const char *, int *, int);
195char *history_arg_extract(int, int, const char *); 195char *history_arg_extract(int, int, const char *);
196 196
197char *tilde_expand(char *); 197char *tilde_expand(char *);
198char *filename_completion_function(const char *, int); 198char *filename_completion_function(const char *, int);
199char *username_completion_function(const char *, int); 199char *username_completion_function(const char *, int);
200int rl_complete(int, int); 200int rl_complete(int, int);
201int rl_read_key(void); 201int rl_read_key(void);
202char **completion_matches(/* const */ char *, rl_compentry_func_t *); 202char **completion_matches(/* const */ char *, rl_compentry_func_t *);
203void rl_display_match_list(char **, int, int); 203void rl_display_match_list(char **, int, int);
204 204
205int rl_insert(int, int); 205int rl_insert(int, int);
206int rl_insert_text(const char *); 206int rl_insert_text(const char *);
207int rl_reset_terminal(const char *); 207int rl_reset_terminal(const char *);
208void rl_resize_terminal(void); 208void rl_resize_terminal(void);
209int rl_bind_key(int, rl_command_func_t *); 209int rl_bind_key(int, rl_command_func_t *);
210int rl_newline(int, int); 210int rl_newline(int, int);
211void rl_callback_read_char(void); 211void rl_callback_read_char(void);
212void rl_callback_handler_install(const char *, rl_vcpfunc_t *); 212void rl_callback_handler_install(const char *, rl_vcpfunc_t *);
213void rl_callback_handler_remove(void); 213void rl_callback_handler_remove(void);
214void rl_redisplay(void); 214void rl_redisplay(void);
215int rl_get_previous_history(int, int); 215int rl_get_previous_history(int, int);
216void rl_prep_terminal(int); 216void rl_prep_terminal(int);
217void rl_deprep_terminal(void); 217void rl_deprep_terminal(void);
218int rl_read_init_file(const char *); 218int rl_read_init_file(const char *);
219int rl_parse_and_bind(const char *); 219int rl_parse_and_bind(const char *);
220int rl_variable_bind(const char *, const char *); 220int rl_variable_bind(const char *, const char *);
221int rl_stuff_char(int); 221int rl_stuff_char(int);
222int rl_add_defun(const char *, rl_command_func_t *, int); 222int rl_add_defun(const char *, rl_command_func_t *, int);
223HISTORY_STATE *history_get_history_state(void); 223HISTORY_STATE *history_get_history_state(void);
224void rl_get_screen_size(int *, int *); 224void rl_get_screen_size(int *, int *);
225void rl_set_screen_size(int, int); 225void rl_set_screen_size(int, int);
226char *rl_filename_completion_function(const char *, int); 226char *rl_filename_completion_function(const char *, int);
227int _rl_abort_internal(void); 227int _rl_abort_internal(void);
228int _rl_qsort_string_compare(char **, char **); 228int _rl_qsort_string_compare(char **, char **);
229char **rl_completion_matches(const char *, rl_compentry_func_t *); 229char **rl_completion_matches(const char *, rl_compentry_func_t *);
230void rl_forced_update_display(void); 230void rl_forced_update_display(void);
231int rl_set_prompt(const char *); 231int rl_set_prompt(const char *);
232int rl_on_new_line(void); 232int rl_on_new_line(void);
233void rl_reset_after_signal(void); 233void rl_reset_after_signal(void);
234void rl_echo_signal_char(int); 234void rl_echo_signal_char(int);
235int rl_crlf(void); 235int rl_crlf(void);
236int rl_ding(void); 236int rl_ding(void);
237char *rl_copy_text(int, int); 237char *rl_copy_text(int, int);
238void rl_replace_line(const char *, int); 238void rl_replace_line(const char *, int);
239int rl_delete_text(int, int); 239int rl_delete_text(int, int);
240void rl_message(const char *format, ...) 240void rl_message(const char *format, ...)
241 __attribute__((__format__(__printf__, 1, 2))); 241 __attribute__((__format__(__printf__, 1, 2)));
242void rl_save_prompt(void); 242void rl_save_prompt(void);
243void rl_restore_prompt(void); 243void rl_restore_prompt(void);
244 244
245/* 245/*
246 * The following are not implemented 246 * The following are not implemented
247 */ 247 */
248int rl_kill_text(int, int); 248int rl_kill_text(int, int);
249Keymap rl_get_keymap(void); 249Keymap rl_get_keymap(void);
250void rl_set_keymap(Keymap); 250void rl_set_keymap(Keymap);
251Keymap rl_make_bare_keymap(void); 251Keymap rl_make_bare_keymap(void);
252int rl_generic_bind(int, const char *, const char *, Keymap); 252int rl_generic_bind(int, const char *, const char *, Keymap);
253int rl_bind_key_in_map(int, rl_command_func_t *, Keymap); 253int rl_bind_key_in_map(int, rl_command_func_t *, Keymap);
254int rl_set_key(const char *, rl_command_func_t *, Keymap); 254int rl_set_key(const char *, rl_command_func_t *, Keymap);
255void rl_cleanup_after_signal(void); 255void rl_cleanup_after_signal(void);
256void rl_free_line_state(void); 256void rl_free_line_state(void);
257int rl_set_keyboard_input_timeout(int); 257int rl_set_keyboard_input_timeout(int);
258int rl_abort(int, int); 258int rl_abort(int, int);
259int rl_set_keymap_name(const char *, Keymap); 259int rl_set_keymap_name(const char *, Keymap);
260histdata_t free_history_entry(HIST_ENTRY *); 260histdata_t free_history_entry(HIST_ENTRY *);
261void _rl_erase_entire_line(void); 261void _rl_erase_entire_line(void);
262 262
263#ifdef __cplusplus 263#ifdef __cplusplus
264} 264}
265#endif 265#endif
266 266
267#endif /* _READLINE_H_ */ 267#endif /* _READLINE_H_ */