Annotation of src/lib/libedit/readline.c, Revision 1.66
1.66 ! christos 1: /* $NetBSD: readline.c,v 1.65 2006/03/18 19:22:59 christos Exp $ */
1.1 christos 2:
3: /*-
4: * Copyright (c) 1997 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Jaromir Dolecek.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
1.20 christos 39: #include "config.h"
1.1 christos 40: #if !defined(lint) && !defined(SCCSID)
1.66 ! christos 41: __RCSID("$NetBSD: readline.c,v 1.65 2006/03/18 19:22:59 christos Exp $");
1.1 christos 42: #endif /* not lint && not SCCSID */
43:
44: #include <sys/types.h>
45: #include <sys/stat.h>
46: #include <stdio.h>
47: #include <dirent.h>
48: #include <string.h>
49: #include <pwd.h>
50: #include <ctype.h>
51: #include <stdlib.h>
52: #include <unistd.h>
53: #include <limits.h>
1.38 christos 54: #include <errno.h>
55: #include <fcntl.h>
56: #ifdef HAVE_VIS_H
1.35 christos 57: #include <vis.h>
1.38 christos 58: #else
59: #include "np/vis.h"
60: #endif
1.27 christos 61: #ifdef HAVE_ALLOCA_H
62: #include <alloca.h>
63: #endif
1.45 christos 64: #include "el.h"
65: #include "fcns.h" /* for EL_NUM_FCNS */
1.1 christos 66: #include "histedit.h"
1.17 jdolecek 67: #include "readline/readline.h"
1.53 dsl 68: #include "filecomplete.h"
1.1 christos 69:
70: /* for rl_complete() */
1.40 christos 71: #define TAB '\r'
1.1 christos 72:
73: /* see comment at the #ifdef for sense of this */
1.40 christos 74: /* #define GDB_411_HACK */
1.1 christos 75:
76: /* readline compatibility stuff - look at readline sources/documentation */
77: /* to see what these variables mean */
1.11 lukem 78: const char *rl_library_version = "EditLine wrapper";
1.20 christos 79: static char empty[] = { '\0' };
80: static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
81: static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
82: '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
83: char *rl_readline_name = empty;
1.11 lukem 84: FILE *rl_instream = NULL;
85: FILE *rl_outstream = NULL;
86: int rl_point = 0;
87: int rl_end = 0;
88: char *rl_line_buffer = NULL;
1.55 agc 89: VCPFunction *rl_linefunc = NULL;
1.38 christos 90: int rl_done = 0;
91: VFunction *rl_event_hook = NULL;
1.11 lukem 92:
93: int history_base = 1; /* probably never subject to change */
94: int history_length = 0;
95: int max_input_history = 0;
96: char history_expansion_char = '!';
97: char history_subst_char = '^';
1.20 christos 98: char *history_no_expand_chars = expand_chars;
1.11 lukem 99: Function *history_inhibit_expansion_function = NULL;
1.40 christos 100: char *history_arg_extract(int start, int end, const char *str);
1.11 lukem 101:
102: int rl_inhibit_completion = 0;
103: int rl_attempted_completion_over = 0;
1.20 christos 104: char *rl_basic_word_break_characters = break_chars;
1.11 lukem 105: char *rl_completer_word_break_characters = NULL;
106: char *rl_completer_quote_characters = NULL;
1.34 christos 107: Function *rl_completion_entry_function = NULL;
1.11 lukem 108: CPPFunction *rl_attempted_completion_function = NULL;
1.32 christos 109: Function *rl_pre_input_hook = NULL;
110: Function *rl_startup1_hook = NULL;
111: Function *rl_getc_function = NULL;
112: char *rl_terminal_name = NULL;
113: int rl_already_prompted = 0;
114: int rl_filename_completion_desired = 0;
115: int rl_ignore_completion_duplicates = 0;
1.39 christos 116: int rl_catch_signals = 1;
1.32 christos 117: VFunction *rl_redisplay_function = NULL;
1.33 christos 118: Function *rl_startup_hook = NULL;
1.34 christos 119: VFunction *rl_completion_display_matches_hook = NULL;
1.33 christos 120: VFunction *rl_prep_term_function = NULL;
121: VFunction *rl_deprep_term_function = NULL;
1.1 christos 122:
1.12 jdolecek 123: /*
1.32 christos 124: * The current prompt string.
125: */
126: char *rl_prompt = NULL;
127: /*
1.12 jdolecek 128: * This is set to character indicating type of completion being done by
129: * rl_complete_internal(); this is available for application completion
130: * functions.
131: */
132: int rl_completion_type = 0;
133:
134: /*
135: * If more than this number of items results from query for possible
136: * completions, we ask user if they are sure to really display the list.
137: */
138: int rl_completion_query_items = 100;
139:
140: /*
1.15 jdolecek 141: * List of characters which are word break characters, but should be left
142: * in the parsed text when it is passed to the completion function.
143: * Shell uses this to help determine what kind of completing to do.
1.12 jdolecek 144: */
1.53 dsl 145: char *rl_special_prefixes = NULL;
1.15 jdolecek 146:
147: /*
148: * This is the character appended to the completed words if at the end of
149: * the line. Default is ' ' (a space).
150: */
151: int rl_completion_append_character = ' ';
152:
153: /* stuff below is used internally by libedit for readline emulation */
154:
1.1 christos 155: static History *h = NULL;
156: static EditLine *e = NULL;
1.35 christos 157: static Function *map[256];
1.1 christos 158:
159: /* internal functions */
1.11 lukem 160: static unsigned char _el_rl_complete(EditLine *, int);
1.46 christos 161: static unsigned char _el_rl_tstp(EditLine *, int);
1.11 lukem 162: static char *_get_prompt(EditLine *);
1.59 christos 163: static int _getc_function(EditLine *, char *);
1.11 lukem 164: static HIST_ENTRY *_move_history(int);
1.40 christos 165: static int _history_expand_command(const char *, size_t, size_t,
166: char **);
1.11 lukem 167: static char *_rl_compat_sub(const char *, const char *,
1.40 christos 168: const char *, int);
1.38 christos 169: static int _rl_event_read_char(EditLine *, char *);
1.49 christos 170: static void _rl_update_pos(void);
1.1 christos 171:
1.5 christos 172:
173: /* ARGSUSED */
1.1 christos 174: static char *
1.30 christos 175: _get_prompt(EditLine *el __attribute__((__unused__)))
1.1 christos 176: {
1.32 christos 177: rl_already_prompted = 1;
178: return (rl_prompt);
1.1 christos 179: }
180:
1.11 lukem 181:
1.1 christos 182: /*
183: * generic function for moving around history
184: */
1.2 christos 185: static HIST_ENTRY *
1.11 lukem 186: _move_history(int op)
1.1 christos 187: {
188: HistEvent ev;
189: static HIST_ENTRY rl_he;
190:
191: if (history(h, &ev, op) != 0)
192: return (HIST_ENTRY *) NULL;
193:
194: rl_he.line = ev.str;
1.40 christos 195: rl_he.data = NULL;
1.1 christos 196:
1.11 lukem 197: return (&rl_he);
1.1 christos 198: }
199:
200:
1.7 simonb 201: /*
1.59 christos 202: * read one key from user defined input function
203: */
204: static int
1.61 christos 205: /*ARGSUSED*/
1.59 christos 206: _getc_function(EditLine *el, char *c)
207: {
208: int i;
209:
210: i = (*rl_getc_function)(NULL, 0);
211: if (i == -1)
212: return 0;
213: *c = i;
214: return 1;
215: }
216:
217:
218: /*
1.7 simonb 219: * READLINE compatibility stuff
1.1 christos 220: */
221:
222: /*
223: * initialize rl compat stuff
224: */
225: int
1.11 lukem 226: rl_initialize(void)
1.1 christos 227: {
228: HistEvent ev;
229: const LineInfo *li;
1.18 christos 230: int editmode = 1;
231: struct termios t;
1.1 christos 232:
233: if (e != NULL)
234: el_end(e);
235: if (h != NULL)
236: history_end(h);
237:
238: if (!rl_instream)
239: rl_instream = stdin;
240: if (!rl_outstream)
241: rl_outstream = stdout;
1.18 christos 242:
243: /*
244: * See if we don't really want to run the editor
245: */
246: if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
247: editmode = 0;
248:
1.4 christos 249: e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
1.18 christos 250:
251: if (!editmode)
252: el_set(e, EL_EDITMODE, 0);
1.1 christos 253:
254: h = history_init();
255: if (!e || !h)
1.11 lukem 256: return (-1);
1.1 christos 257:
1.4 christos 258: history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
1.1 christos 259: history_length = 0;
260: max_input_history = INT_MAX;
261: el_set(e, EL_HIST, history, h);
262:
1.59 christos 263: /* setup getc function if valid */
264: if (rl_getc_function)
265: el_set(e, EL_GETCFN, _getc_function);
266:
1.1 christos 267: /* for proper prompt printing in readline() */
1.32 christos 268: rl_prompt = strdup("");
269: if (rl_prompt == NULL) {
1.23 christos 270: history_end(h);
271: el_end(e);
272: return -1;
273: }
1.1 christos 274: el_set(e, EL_PROMPT, _get_prompt);
1.39 christos 275: el_set(e, EL_SIGNAL, rl_catch_signals);
1.1 christos 276:
277: /* set default mode to "emacs"-style and read setting afterwards */
278: /* so this can be overriden */
279: el_set(e, EL_EDITOR, "emacs");
1.32 christos 280: if (rl_terminal_name != NULL)
281: el_set(e, EL_TERMINAL, rl_terminal_name);
282: else
283: el_get(e, EL_TERMINAL, &rl_terminal_name);
1.1 christos 284:
1.12 jdolecek 285: /*
1.35 christos 286: * Word completion - this has to go AFTER rebinding keys
1.12 jdolecek 287: * to emacs-style.
288: */
1.1 christos 289: el_set(e, EL_ADDFN, "rl_complete",
1.35 christos 290: "ReadLine compatible completion function",
1.11 lukem 291: _el_rl_complete);
1.1 christos 292: el_set(e, EL_BIND, "^I", "rl_complete", NULL);
1.46 christos 293:
294: /*
295: * Send TSTP when ^Z is pressed.
296: */
297: el_set(e, EL_ADDFN, "rl_tstp",
298: "ReadLine compatible suspend function",
299: _el_rl_tstp);
300: el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
1.12 jdolecek 301:
1.1 christos 302: /* read settings from configuration file */
303: el_source(e, NULL);
304:
1.12 jdolecek 305: /*
306: * Unfortunately, some applications really do use rl_point
307: * and rl_line_buffer directly.
308: */
1.1 christos 309: li = el_line(e);
1.20 christos 310: /* a cheesy way to get rid of const cast. */
311: rl_line_buffer = memchr(li->buffer, *li->buffer, 1);
1.49 christos 312: _rl_update_pos();
1.1 christos 313:
1.32 christos 314: if (rl_startup_hook)
315: (*rl_startup_hook)(NULL, 0);
316:
1.11 lukem 317: return (0);
1.1 christos 318: }
319:
1.11 lukem 320:
1.1 christos 321: /*
322: * read one line from input stream and return it, chomping
323: * trailing newline (if there is any)
324: */
325: char *
326: readline(const char *prompt)
327: {
328: HistEvent ev;
1.3 thorpej 329: int count;
1.1 christos 330: const char *ret;
1.20 christos 331: char *buf;
1.38 christos 332: static int used_event_hook;
1.1 christos 333:
334: if (e == NULL || h == NULL)
335: rl_initialize();
336:
1.38 christos 337: rl_done = 0;
338:
1.9 jdolecek 339: /* update prompt accordingly to what has been passed */
1.11 lukem 340: if (!prompt)
341: prompt = "";
1.32 christos 342: if (strcmp(rl_prompt, prompt) != 0) {
343: free(rl_prompt);
344: rl_prompt = strdup(prompt);
345: if (rl_prompt == NULL)
1.23 christos 346: return NULL;
1.1 christos 347: }
1.32 christos 348:
349: if (rl_pre_input_hook)
350: (*rl_pre_input_hook)(NULL, 0);
351:
1.38 christos 352: if (rl_event_hook && !(e->el_flags&NO_TTY)) {
353: el_set(e, EL_GETCFN, _rl_event_read_char);
354: used_event_hook = 1;
355: }
356:
357: if (!rl_event_hook && used_event_hook) {
358: el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
359: used_event_hook = 0;
360: }
361:
1.32 christos 362: rl_already_prompted = 0;
363:
1.1 christos 364: /* get one line from input stream */
365: ret = el_gets(e, &count);
366:
367: if (ret && count > 0) {
1.5 christos 368: int lastidx;
1.1 christos 369:
1.20 christos 370: buf = strdup(ret);
1.23 christos 371: if (buf == NULL)
372: return NULL;
1.1 christos 373: lastidx = count - 1;
1.20 christos 374: if (buf[lastidx] == '\n')
375: buf[lastidx] = '\0';
1.1 christos 376: } else
1.20 christos 377: buf = NULL;
1.1 christos 378:
379: history(h, &ev, H_GETSIZE);
380: history_length = ev.num;
381:
1.20 christos 382: return buf;
1.1 christos 383: }
384:
385: /*
386: * history functions
387: */
388:
389: /*
390: * is normally called before application starts to use
391: * history expansion functions
392: */
393: void
1.11 lukem 394: using_history(void)
1.1 christos 395: {
396: if (h == NULL || e == NULL)
397: rl_initialize();
398: }
399:
1.11 lukem 400:
1.1 christos 401: /*
402: * substitute ``what'' with ``with'', returning resulting string; if
1.29 wiz 403: * globally == 1, substitutes all occurrences of what, otherwise only the
1.1 christos 404: * first one
405: */
1.11 lukem 406: static char *
407: _rl_compat_sub(const char *str, const char *what, const char *with,
408: int globally)
409: {
1.40 christos 410: const char *s;
411: char *r, *result;
412: size_t len, with_len, what_len;
1.1 christos 413:
1.40 christos 414: len = strlen(str);
415: with_len = strlen(with);
416: what_len = strlen(what);
417:
418: /* calculate length we need for result */
419: s = str;
420: while (*s) {
421: if (*s == *what && !strncmp(s, what, what_len)) {
422: len += with_len - what_len;
423: if (!globally)
424: break;
425: s += what_len;
426: } else
427: s++;
428: }
429: r = result = malloc(len + 1);
1.23 christos 430: if (result == NULL)
431: return NULL;
1.40 christos 432: s = str;
433: while (*s) {
434: if (*s == *what && !strncmp(s, what, what_len)) {
435: (void)strncpy(r, with, with_len);
436: r += with_len;
437: s += what_len;
438: if (!globally) {
439: (void)strcpy(r, s);
440: return(result);
1.1 christos 441: }
1.40 christos 442: } else
443: *r++ = *s++;
444: }
445: *r = 0;
446: return(result);
447: }
448:
449: static char *last_search_pat; /* last !?pat[?] search pattern */
450: static char *last_search_match; /* last !?pat[?] that matched */
451:
452: const char *
453: get_history_event(const char *cmd, int *cindex, int qchar)
454: {
455: int idx, sign, sub, num, begin, ret;
456: size_t len;
457: char *pat;
458: const char *rptr;
459: HistEvent ev;
460:
461: idx = *cindex;
462: if (cmd[idx++] != history_expansion_char)
463: return(NULL);
464:
465: /* find out which event to take */
466: if (cmd[idx] == history_expansion_char || cmd[idx] == 0) {
467: if (history(h, &ev, H_FIRST) != 0)
468: return(NULL);
469: *cindex = cmd[idx]? (idx + 1):idx;
470: return(ev.str);
471: }
472: sign = 0;
473: if (cmd[idx] == '-') {
474: sign = 1;
475: idx++;
476: }
477:
478: if ('0' <= cmd[idx] && cmd[idx] <= '9') {
479: HIST_ENTRY *rl_he;
480:
481: num = 0;
482: while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
483: num = num * 10 + cmd[idx] - '0';
484: idx++;
485: }
486: if (sign)
487: num = history_length - num + 1;
488:
489: if (!(rl_he = history_get(num)))
490: return(NULL);
491:
492: *cindex = idx;
493: return(rl_he->line);
494: }
495: sub = 0;
496: if (cmd[idx] == '?') {
497: sub = 1;
498: idx++;
499: }
500: begin = idx;
501: while (cmd[idx]) {
502: if (cmd[idx] == '\n')
503: break;
504: if (sub && cmd[idx] == '?')
505: break;
506: if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
507: || cmd[idx] == '\t' || cmd[idx] == qchar))
508: break;
509: idx++;
510: }
511: len = idx - begin;
512: if (sub && cmd[idx] == '?')
513: idx++;
514: if (sub && len == 0 && last_search_pat && *last_search_pat)
515: pat = last_search_pat;
516: else if (len == 0)
517: return(NULL);
518: else {
519: if ((pat = malloc(len + 1)) == NULL)
520: return NULL;
521: (void)strncpy(pat, cmd + begin, len);
522: pat[len] = '\0';
523: }
524:
525: if (history(h, &ev, H_CURR) != 0) {
526: if (pat != last_search_pat)
527: free(pat);
528: return (NULL);
529: }
530: num = ev.num;
531:
532: if (sub) {
533: if (pat != last_search_pat) {
534: if (last_search_pat)
535: free(last_search_pat);
536: last_search_pat = pat;
1.1 christos 537: }
1.40 christos 538: ret = history_search(pat, -1);
539: } else
540: ret = history_search_prefix(pat, -1);
541:
542: if (ret == -1) {
543: /* restore to end of list on failed search */
544: history(h, &ev, H_FIRST);
545: (void)fprintf(rl_outstream, "%s: Event not found\n", pat);
546: if (pat != last_search_pat)
547: free(pat);
548: return(NULL);
549: }
550:
551: if (sub && len) {
552: if (last_search_match && last_search_match != pat)
553: free(last_search_match);
554: last_search_match = pat;
555: }
556:
557: if (pat != last_search_pat)
558: free(pat);
559:
560: if (history(h, &ev, H_CURR) != 0)
561: return(NULL);
562: *cindex = idx;
563: rptr = ev.str;
564:
565: /* roll back to original position */
566: (void)history(h, &ev, H_SET, num);
1.1 christos 567:
1.40 christos 568: return rptr;
1.1 christos 569: }
570:
571: /*
572: * the real function doing history expansion - takes as argument command
573: * to do and data upon which the command should be executed
574: * does expansion the way I've understood readline documentation
575: *
576: * returns 0 if data was not modified, 1 if it was and 2 if the string
577: * should be only printed and not executed; in case of error,
578: * returns -1 and *result points to NULL
579: * it's callers responsibility to free() string returned in *result
580: */
581: static int
1.40 christos 582: _history_expand_command(const char *command, size_t offs, size_t cmdlen,
583: char **result)
1.11 lukem 584: {
1.40 christos 585: char *tmp, *search = NULL, *aptr;
586: const char *ptr, *cmd;
1.11 lukem 587: static char *from = NULL, *to = NULL;
1.40 christos 588: int start, end, idx, has_mods = 0;
589: int p_on = 0, g_on = 0;
1.1 christos 590:
591: *result = NULL;
1.40 christos 592: aptr = NULL;
1.41 christos 593: ptr = NULL;
1.1 christos 594:
1.40 christos 595: /* First get event specifier */
596: idx = 0;
1.1 christos 597:
1.40 christos 598: if (strchr(":^*$", command[offs + 1])) {
599: char str[4];
600: /*
601: * "!:" is shorthand for "!!:".
602: * "!^", "!*" and "!$" are shorthand for
603: * "!!:^", "!!:*" and "!!:$" respectively.
604: */
605: str[0] = str[1] = '!';
606: str[2] = '0';
607: ptr = get_history_event(str, &idx, 0);
608: idx = (command[offs + 1] == ':')? 1:0;
609: has_mods = 1;
1.1 christos 610: } else {
1.40 christos 611: if (command[offs + 1] == '#') {
612: /* use command so far */
613: if ((aptr = malloc(offs + 1)) == NULL)
614: return -1;
615: (void)strncpy(aptr, command, offs);
616: aptr[offs] = '\0';
617: idx = 1;
1.1 christos 618: } else {
1.40 christos 619: int qchar;
620:
621: qchar = (offs > 0 && command[offs - 1] == '"')? '"':0;
622: ptr = get_history_event(command + offs, &idx, qchar);
623: }
624: has_mods = command[offs + idx] == ':';
625: }
1.1 christos 626:
1.40 christos 627: if (ptr == NULL && aptr == NULL)
628: return(-1);
1.1 christos 629:
1.40 christos 630: if (!has_mods) {
631: *result = strdup(aptr? aptr : ptr);
632: if (aptr)
633: free(aptr);
634: return(1);
635: }
636:
637: cmd = command + offs + idx + 1;
638:
639: /* Now parse any word designators */
640:
641: if (*cmd == '%') /* last word matched by ?pat? */
642: tmp = strdup(last_search_match? last_search_match:"");
643: else if (strchr("^*$-0123456789", *cmd)) {
644: start = end = -1;
645: if (*cmd == '^')
646: start = end = 1, cmd++;
647: else if (*cmd == '$')
648: start = -1, cmd++;
649: else if (*cmd == '*')
650: start = 1, cmd++;
651: else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
652: start = 0;
653: while (*cmd && '0' <= *cmd && *cmd <= '9')
654: start = start * 10 + *cmd++ - '0';
655:
656: if (*cmd == '-') {
657: if (isdigit((unsigned char) cmd[1])) {
658: cmd++;
659: end = 0;
660: while (*cmd && '0' <= *cmd && *cmd <= '9')
661: end = end * 10 + *cmd++ - '0';
662: } else if (cmd[1] == '$') {
663: cmd += 2;
664: end = -1;
665: } else {
666: cmd++;
667: end = -2;
668: }
669: } else if (*cmd == '*')
670: end = -1, cmd++;
1.1 christos 671: else
1.40 christos 672: end = start;
673: }
674: tmp = history_arg_extract(start, end, aptr? aptr:ptr);
675: if (tmp == NULL) {
676: (void)fprintf(rl_outstream, "%s: Bad word specifier",
677: command + offs + idx);
678: if (aptr)
679: free(aptr);
680: return(-1);
681: }
682: } else
683: tmp = strdup(aptr? aptr:ptr);
1.1 christos 684:
1.40 christos 685: if (aptr)
686: free(aptr);
1.1 christos 687:
1.40 christos 688: if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) {
689: *result = tmp;
690: return(1);
1.1 christos 691: }
692:
693: for (; *cmd; cmd++) {
694: if (*cmd == ':')
695: continue;
1.40 christos 696: else if (*cmd == 'h') { /* remove trailing path */
697: if ((aptr = strrchr(tmp, '/')) != NULL)
698: *aptr = 0;
699: } else if (*cmd == 't') { /* remove leading path */
700: if ((aptr = strrchr(tmp, '/')) != NULL) {
701: aptr = strdup(aptr + 1);
702: free(tmp);
703: tmp = aptr;
704: }
705: } else if (*cmd == 'r') { /* remove trailing suffix */
706: if ((aptr = strrchr(tmp, '.')) != NULL)
707: *aptr = 0;
708: } else if (*cmd == 'e') { /* remove all but suffix */
709: if ((aptr = strrchr(tmp, '.')) != NULL) {
710: aptr = strdup(aptr);
711: free(tmp);
712: tmp = aptr;
713: }
714: } else if (*cmd == 'p') /* print only */
715: p_on = 1;
1.1 christos 716: else if (*cmd == 'g')
717: g_on = 2;
718: else if (*cmd == 's' || *cmd == '&') {
1.11 lukem 719: char *what, *with, delim;
1.30 christos 720: size_t len, from_len;
1.5 christos 721: size_t size;
1.1 christos 722:
723: if (*cmd == '&' && (from == NULL || to == NULL))
724: continue;
725: else if (*cmd == 's') {
726: delim = *(++cmd), cmd++;
727: size = 16;
1.5 christos 728: what = realloc(from, size);
1.23 christos 729: if (what == NULL) {
730: free(from);
1.62 christos 731: free(tmp);
1.28 christos 732: return 0;
1.23 christos 733: }
1.1 christos 734: len = 0;
735: for (; *cmd && *cmd != delim; cmd++) {
1.40 christos 736: if (*cmd == '\\' && cmd[1] == delim)
1.1 christos 737: cmd++;
1.23 christos 738: if (len >= size) {
739: char *nwhat;
740: nwhat = realloc(what,
1.40 christos 741: (size <<= 1));
1.23 christos 742: if (nwhat == NULL) {
743: free(what);
1.62 christos 744: free(tmp);
1.28 christos 745: return 0;
1.23 christos 746: }
747: what = nwhat;
748: }
1.1 christos 749: what[len++] = *cmd;
750: }
751: what[len] = '\0';
752: from = what;
753: if (*what == '\0') {
754: free(what);
1.23 christos 755: if (search) {
1.1 christos 756: from = strdup(search);
1.62 christos 757: if (from == NULL) {
758: free(tmp);
1.28 christos 759: return 0;
1.62 christos 760: }
1.23 christos 761: } else {
1.1 christos 762: from = NULL;
1.62 christos 763: free(tmp);
1.11 lukem 764: return (-1);
1.1 christos 765: }
766: }
767: cmd++; /* shift after delim */
768: if (!*cmd)
769: continue;
770:
771: size = 16;
1.5 christos 772: with = realloc(to, size);
1.23 christos 773: if (with == NULL) {
774: free(to);
1.62 christos 775: free(tmp);
1.23 christos 776: return -1;
777: }
1.1 christos 778: len = 0;
779: from_len = strlen(from);
780: for (; *cmd && *cmd != delim; cmd++) {
781: if (len + from_len + 1 >= size) {
1.23 christos 782: char *nwith;
1.1 christos 783: size += from_len + 1;
1.23 christos 784: nwith = realloc(with, size);
785: if (nwith == NULL) {
786: free(with);
1.62 christos 787: free(tmp);
1.23 christos 788: return -1;
789: }
790: with = nwith;
1.1 christos 791: }
792: if (*cmd == '&') {
793: /* safe */
1.40 christos 794: (void)strcpy(&with[len], from);
1.1 christos 795: len += from_len;
796: continue;
797: }
798: if (*cmd == '\\'
799: && (*(cmd + 1) == delim
800: || *(cmd + 1) == '&'))
801: cmd++;
802: with[len++] = *cmd;
803: }
804: with[len] = '\0';
805: to = with;
806: }
807:
1.40 christos 808: aptr = _rl_compat_sub(tmp, from, to, g_on);
809: if (aptr) {
810: free(tmp);
811: tmp = aptr;
1.23 christos 812: }
1.40 christos 813: g_on = 0;
1.1 christos 814: }
1.5 christos 815: }
1.40 christos 816: *result = tmp;
817: return (p_on? 2:1);
1.1 christos 818: }
819:
1.11 lukem 820:
1.1 christos 821: /*
822: * csh-style history expansion
823: */
824: int
1.11 lukem 825: history_expand(char *str, char **output)
826: {
1.40 christos 827: int ret = 0;
828: size_t idx, i, size;
829: char *tmp, *result;
1.1 christos 830:
831: if (h == NULL || e == NULL)
832: rl_initialize();
833:
1.40 christos 834: if (history_expansion_char == 0) {
835: *output = strdup(str);
836: return(0);
837: }
1.1 christos 838:
1.40 christos 839: *output = NULL;
1.1 christos 840: if (str[0] == history_subst_char) {
841: /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
1.40 christos 842: *output = malloc(strlen(str) + 4 + 1);
843: if (*output == NULL)
844: return 0;
845: (*output)[0] = (*output)[1] = history_expansion_char;
846: (*output)[2] = ':';
847: (*output)[3] = 's';
848: (void)strcpy((*output) + 4, str);
849: str = *output;
850: } else {
851: *output = strdup(str);
852: if (*output == NULL)
853: return 0;
1.1 christos 854: }
1.40 christos 855:
1.63 christos 856: #define ADD_STRING(what, len, fr) \
1.1 christos 857: { \
1.23 christos 858: if (idx + len + 1 > size) { \
859: char *nresult = realloc(result, (size += len + 1));\
860: if (nresult == NULL) { \
861: free(*output); \
1.65 christos 862: if (/*CONSTCOND*/fr) \
1.63 christos 863: free(tmp); \
1.28 christos 864: return 0; \
1.23 christos 865: } \
866: result = nresult; \
867: } \
1.1 christos 868: (void)strncpy(&result[idx], what, len); \
869: idx += len; \
870: result[idx] = '\0'; \
871: }
872:
873: result = NULL;
874: size = idx = 0;
1.64 christos 875: tmp = NULL;
1.1 christos 876: for (i = 0; str[i];) {
1.40 christos 877: int qchar, loop_again;
878: size_t len, start, j;
1.1 christos 879:
1.40 christos 880: qchar = 0;
1.1 christos 881: loop_again = 1;
882: start = j = i;
883: loop:
884: for (; str[j]; j++) {
885: if (str[j] == '\\' &&
886: str[j + 1] == history_expansion_char) {
1.40 christos 887: (void)strcpy(&str[j], &str[j + 1]);
1.1 christos 888: continue;
889: }
890: if (!loop_again) {
1.40 christos 891: if (isspace((unsigned char) str[j])
892: || str[j] == qchar)
1.1 christos 893: break;
894: }
895: if (str[j] == history_expansion_char
896: && !strchr(history_no_expand_chars, str[j + 1])
897: && (!history_inhibit_expansion_function ||
1.40 christos 898: (*history_inhibit_expansion_function)(str,
899: (int)j) == 0))
1.1 christos 900: break;
901: }
902:
1.40 christos 903: if (str[j] && loop_again) {
1.1 christos 904: i = j;
1.40 christos 905: qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
1.1 christos 906: j++;
907: if (str[j] == history_expansion_char)
908: j++;
909: loop_again = 0;
910: goto loop;
911: }
912: len = i - start;
1.64 christos 913: ADD_STRING(&str[start], len, 0);
1.1 christos 914:
1.40 christos 915: if (str[i] == '\0' || str[i] != history_expansion_char) {
1.1 christos 916: len = j - i;
1.64 christos 917: ADD_STRING(&str[i], len, 0);
1.1 christos 918: if (start == 0)
1.40 christos 919: ret = 0;
1.1 christos 920: else
1.40 christos 921: ret = 1;
1.1 christos 922: break;
923: }
1.64 christos 924: if (tmp) {
925: free(tmp);
926: tmp = NULL;
927: }
1.40 christos 928: ret = _history_expand_command (str, i, (j - i), &tmp);
929: if (ret > 0 && tmp) {
930: len = strlen(tmp);
1.63 christos 931: ADD_STRING(tmp, len, 1);
1.66 ! christos 932: }
! 933: if (tmp) {
1.40 christos 934: free(tmp);
1.64 christos 935: tmp = NULL;
1.1 christos 936: }
937: i = j;
1.40 christos 938: }
1.1 christos 939:
1.40 christos 940: /* ret is 2 for "print only" option */
941: if (ret == 2) {
942: add_history(result);
1.1 christos 943: #ifdef GDB_411_HACK
944: /* gdb 4.11 has been shipped with readline, where */
945: /* history_expand() returned -1 when the line */
946: /* should not be executed; in readline 2.1+ */
947: /* it should return 2 in such a case */
1.40 christos 948: ret = -1;
1.1 christos 949: #endif
950: }
951: free(*output);
952: *output = result;
953:
1.40 christos 954: return (ret);
1.1 christos 955: }
956:
1.40 christos 957: /*
958: * Return a string consisting of arguments of "str" from "start" to "end".
959: */
960: char *
961: history_arg_extract(int start, int end, const char *str)
962: {
963: size_t i, len, max;
964: char **arr, *result;
965:
966: arr = history_tokenize(str);
967: if (!arr)
968: return(NULL);
969: if (arr && *arr == NULL) {
970: free(arr);
971: return(NULL);
972: }
973:
974: for (max = 0; arr[max]; max++)
975: continue;
976: max--;
977:
978: if (start == '$')
979: start = max;
980: if (end == '$')
981: end = max;
982: if (end < 0)
983: end = max + end + 1;
984: if (start < 0)
985: start = end;
986:
987: if (start < 0 || end < 0 || start > max || end > max || start > end)
988: return(NULL);
989:
990: for (i = start, len = 0; i <= end; i++)
991: len += strlen(arr[i]) + 1;
992: len++;
993: result = malloc(len);
994: if (result == NULL)
995: return NULL;
996:
997: for (i = start, len = 0; i <= end; i++) {
998: (void)strcpy(result + len, arr[i]);
999: len += strlen(arr[i]);
1000: if (i < end)
1001: result[len++] = ' ';
1002: }
1003: result[len] = 0;
1004:
1005: for (i = 0; arr[i]; i++)
1006: free(arr[i]);
1007: free(arr);
1008:
1009: return(result);
1010: }
1.11 lukem 1011:
1.1 christos 1012: /*
1.40 christos 1013: * Parse the string into individual tokens,
1014: * similar to how shell would do it.
1.1 christos 1015: */
1016: char **
1.11 lukem 1017: history_tokenize(const char *str)
1.1 christos 1018: {
1.40 christos 1019: int size = 1, idx = 0, i, start;
1.5 christos 1020: size_t len;
1.1 christos 1021: char **result = NULL, *temp, delim = '\0';
1022:
1.40 christos 1023: for (i = 0; str[i];) {
1.4 christos 1024: while (isspace((unsigned char) str[i]))
1.1 christos 1025: i++;
1026: start = i;
1.40 christos 1027: for (; str[i];) {
1.9 jdolecek 1028: if (str[i] == '\\') {
1.14 jdolecek 1029: if (str[i+1] != '\0')
1.9 jdolecek 1030: i++;
1031: } else if (str[i] == delim)
1.1 christos 1032: delim = '\0';
1033: else if (!delim &&
1.11 lukem 1034: (isspace((unsigned char) str[i]) ||
1035: strchr("()<>;&|$", str[i])))
1.1 christos 1036: break;
1037: else if (!delim && strchr("'`\"", str[i]))
1038: delim = str[i];
1.40 christos 1039: if (str[i])
1040: i++;
1.1 christos 1041: }
1042:
1.40 christos 1043: if (idx + 2 >= size) {
1.23 christos 1044: char **nresult;
1.1 christos 1045: size <<= 1;
1.23 christos 1046: nresult = realloc(result, size * sizeof(char *));
1047: if (nresult == NULL) {
1048: free(result);
1049: return NULL;
1050: }
1051: result = nresult;
1.1 christos 1052: }
1053: len = i - start;
1054: temp = malloc(len + 1);
1.23 christos 1055: if (temp == NULL) {
1.40 christos 1056: for (i = 0; i < idx; i++)
1057: free(result[i]);
1.23 christos 1058: free(result);
1059: return NULL;
1060: }
1.40 christos 1061: (void)strncpy(temp, &str[start], len);
1.1 christos 1062: temp[len] = '\0';
1.40 christos 1063: result[idx++] = temp;
1064: result[idx] = NULL;
1065: if (str[i])
1066: i++;
1.1 christos 1067: }
1.11 lukem 1068: return (result);
1.1 christos 1069: }
1070:
1.11 lukem 1071:
1.1 christos 1072: /*
1073: * limit size of history record to ``max'' events
1074: */
1075: void
1.11 lukem 1076: stifle_history(int max)
1.1 christos 1077: {
1078: HistEvent ev;
1079:
1080: if (h == NULL || e == NULL)
1081: rl_initialize();
1082:
1.4 christos 1083: if (history(h, &ev, H_SETSIZE, max) == 0)
1.1 christos 1084: max_input_history = max;
1085: }
1086:
1.11 lukem 1087:
1.1 christos 1088: /*
1089: * "unlimit" size of history - set the limit to maximum allowed int value
1090: */
1091: int
1.11 lukem 1092: unstifle_history(void)
1.1 christos 1093: {
1094: HistEvent ev;
1095: int omax;
1096:
1.4 christos 1097: history(h, &ev, H_SETSIZE, INT_MAX);
1.1 christos 1098: omax = max_input_history;
1099: max_input_history = INT_MAX;
1.11 lukem 1100: return (omax); /* some value _must_ be returned */
1.1 christos 1101: }
1102:
1.11 lukem 1103:
1.1 christos 1104: int
1.11 lukem 1105: history_is_stifled(void)
1.1 christos 1106: {
1.11 lukem 1107:
1.1 christos 1108: /* cannot return true answer */
1109: return (max_input_history != INT_MAX);
1110: }
1111:
1.11 lukem 1112:
1.1 christos 1113: /*
1114: * read history from a file given
1115: */
1116: int
1.11 lukem 1117: read_history(const char *filename)
1.1 christos 1118: {
1119: HistEvent ev;
1120:
1121: if (h == NULL || e == NULL)
1122: rl_initialize();
1.60 christos 1123: return (history(h, &ev, H_LOAD, filename) == -1);
1.1 christos 1124: }
1125:
1.11 lukem 1126:
1.1 christos 1127: /*
1128: * write history to a file given
1129: */
1130: int
1.11 lukem 1131: write_history(const char *filename)
1.1 christos 1132: {
1133: HistEvent ev;
1134:
1135: if (h == NULL || e == NULL)
1136: rl_initialize();
1.60 christos 1137: return (history(h, &ev, H_SAVE, filename) == -1);
1.1 christos 1138: }
1139:
1.11 lukem 1140:
1.1 christos 1141: /*
1142: * returns history ``num''th event
1143: *
1144: * returned pointer points to static variable
1145: */
1.2 christos 1146: HIST_ENTRY *
1.11 lukem 1147: history_get(int num)
1.1 christos 1148: {
1149: static HIST_ENTRY she;
1150: HistEvent ev;
1.40 christos 1151: int curr_num;
1.1 christos 1152:
1153: if (h == NULL || e == NULL)
1154: rl_initialize();
1155:
1.40 christos 1156: /* save current position */
1.1 christos 1157: if (history(h, &ev, H_CURR) != 0)
1.11 lukem 1158: return (NULL);
1.1 christos 1159: curr_num = ev.num;
1.40 christos 1160:
1161: /* start from most recent */
1162: if (history(h, &ev, H_FIRST) != 0)
1.11 lukem 1163: return (NULL); /* error */
1.40 christos 1164:
1165: /* look backwards for event matching specified offset */
1166: if (history(h, &ev, H_NEXT_EVENT, num))
1167: return (NULL);
1.1 christos 1168:
1169: she.line = ev.str;
1170: she.data = NULL;
1171:
1.40 christos 1172: /* restore pointer to where it was */
1173: (void)history(h, &ev, H_SET, curr_num);
1.1 christos 1174:
1.11 lukem 1175: return (&she);
1.1 christos 1176: }
1177:
1.11 lukem 1178:
1.1 christos 1179: /*
1180: * add the line to history table
1181: */
1182: int
1.11 lukem 1183: add_history(const char *line)
1.1 christos 1184: {
1185: HistEvent ev;
1186:
1187: if (h == NULL || e == NULL)
1188: rl_initialize();
1189:
1.40 christos 1190: (void)history(h, &ev, H_ENTER, line);
1.1 christos 1191: if (history(h, &ev, H_GETSIZE) == 0)
1192: history_length = ev.num;
1193:
1.40 christos 1194: return (!(history_length > 0)); /* return 0 if all is okay */
1.1 christos 1195: }
1196:
1.11 lukem 1197:
1.1 christos 1198: /*
1.58 christos 1199: * remove the specified entry from the history list and return it.
1200: */
1201: HIST_ENTRY *
1202: remove_history(int num)
1203: {
1204: static HIST_ENTRY she;
1205: HistEvent ev;
1206:
1207: if (h == NULL || e == NULL)
1208: rl_initialize();
1209:
1210: if (history(h, &ev, H_DEL, num) != 0)
1211: return NULL;
1212:
1213: she.line = ev.str;
1214: she.data = NULL;
1215:
1216: return &she;
1217: }
1218:
1219:
1220: /*
1.1 christos 1221: * clear the history list - delete all entries
1222: */
1223: void
1.11 lukem 1224: clear_history(void)
1.1 christos 1225: {
1226: HistEvent ev;
1.11 lukem 1227:
1.1 christos 1228: history(h, &ev, H_CLEAR);
1229: }
1230:
1.11 lukem 1231:
1.1 christos 1232: /*
1233: * returns offset of the current history event
1234: */
1235: int
1.11 lukem 1236: where_history(void)
1.1 christos 1237: {
1238: HistEvent ev;
1239: int curr_num, off;
1240:
1241: if (history(h, &ev, H_CURR) != 0)
1.11 lukem 1242: return (0);
1.1 christos 1243: curr_num = ev.num;
1244:
1245: history(h, &ev, H_FIRST);
1246: off = 1;
1247: while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
1248: off++;
1249:
1.11 lukem 1250: return (off);
1.1 christos 1251: }
1252:
1.11 lukem 1253:
1.1 christos 1254: /*
1255: * returns current history event or NULL if there is no such event
1256: */
1.2 christos 1257: HIST_ENTRY *
1.11 lukem 1258: current_history(void)
1.1 christos 1259: {
1.11 lukem 1260:
1261: return (_move_history(H_CURR));
1.1 christos 1262: }
1263:
1.11 lukem 1264:
1.1 christos 1265: /*
1266: * returns total number of bytes history events' data are using
1267: */
1268: int
1.11 lukem 1269: history_total_bytes(void)
1.1 christos 1270: {
1271: HistEvent ev;
1272: int curr_num, size;
1273:
1274: if (history(h, &ev, H_CURR) != 0)
1.11 lukem 1275: return (-1);
1.1 christos 1276: curr_num = ev.num;
1277:
1278: history(h, &ev, H_FIRST);
1279: size = 0;
1280: do
1281: size += strlen(ev.str);
1282: while (history(h, &ev, H_NEXT) == 0);
1283:
1284: /* get to the same position as before */
1285: history(h, &ev, H_PREV_EVENT, curr_num);
1286:
1.11 lukem 1287: return (size);
1.1 christos 1288: }
1289:
1.11 lukem 1290:
1.1 christos 1291: /*
1292: * sets the position in the history list to ``pos''
1293: */
1294: int
1.11 lukem 1295: history_set_pos(int pos)
1.1 christos 1296: {
1297: HistEvent ev;
1.40 christos 1298: int curr_num;
1.1 christos 1299:
1300: if (pos > history_length || pos < 0)
1.11 lukem 1301: return (-1);
1.1 christos 1302:
1303: history(h, &ev, H_CURR);
1304: curr_num = ev.num;
1305:
1.40 christos 1306: if (history(h, &ev, H_SET, pos)) {
1307: history(h, &ev, H_SET, curr_num);
1308: return(-1);
1.1 christos 1309: }
1.11 lukem 1310: return (0);
1.1 christos 1311: }
1312:
1.11 lukem 1313:
1.1 christos 1314: /*
1315: * returns previous event in history and shifts pointer accordingly
1316: */
1.2 christos 1317: HIST_ENTRY *
1.11 lukem 1318: previous_history(void)
1.1 christos 1319: {
1.11 lukem 1320:
1321: return (_move_history(H_PREV));
1.1 christos 1322: }
1323:
1.11 lukem 1324:
1.1 christos 1325: /*
1326: * returns next event in history and shifts pointer accordingly
1327: */
1.2 christos 1328: HIST_ENTRY *
1.11 lukem 1329: next_history(void)
1.1 christos 1330: {
1.11 lukem 1331:
1332: return (_move_history(H_NEXT));
1.1 christos 1333: }
1334:
1.11 lukem 1335:
1.1 christos 1336: /*
1.40 christos 1337: * searches for first history event containing the str
1.1 christos 1338: */
1.40 christos 1339: int
1340: history_search(const char *str, int direction)
1.11 lukem 1341: {
1342: HistEvent ev;
1343: const char *strp;
1344: int curr_num;
1.1 christos 1345:
1346: if (history(h, &ev, H_CURR) != 0)
1.11 lukem 1347: return (-1);
1.1 christos 1348: curr_num = ev.num;
1349:
1350: for (;;) {
1.40 christos 1351: if ((strp = strstr(ev.str, str)) != NULL)
1.1 christos 1352: return (int) (strp - ev.str);
1.40 christos 1353: if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
1.1 christos 1354: break;
1355: }
1.40 christos 1356: history(h, &ev, H_SET, curr_num);
1.11 lukem 1357: return (-1);
1.1 christos 1358: }
1359:
1.11 lukem 1360:
1.1 christos 1361: /*
1362: * searches for first history event beginning with str
1363: */
1364: int
1.11 lukem 1365: history_search_prefix(const char *str, int direction)
1.1 christos 1366: {
1.40 christos 1367: HistEvent ev;
1.11 lukem 1368:
1.40 christos 1369: return (history(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str));
1.1 christos 1370: }
1371:
1.11 lukem 1372:
1.1 christos 1373: /*
1374: * search for event in history containing str, starting at offset
1375: * abs(pos); continue backward, if pos<0, forward otherwise
1376: */
1.5 christos 1377: /* ARGSUSED */
1.1 christos 1378: int
1.40 christos 1379: history_search_pos(const char *str,
1.30 christos 1380: int direction __attribute__((__unused__)), int pos)
1.1 christos 1381: {
1.11 lukem 1382: HistEvent ev;
1383: int curr_num, off;
1.1 christos 1384:
1385: off = (pos > 0) ? pos : -pos;
1386: pos = (pos > 0) ? 1 : -1;
1387:
1388: if (history(h, &ev, H_CURR) != 0)
1.11 lukem 1389: return (-1);
1.1 christos 1390: curr_num = ev.num;
1391:
1392: if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
1.11 lukem 1393: return (-1);
1.1 christos 1394:
1395:
1396: for (;;) {
1397: if (strstr(ev.str, str))
1.11 lukem 1398: return (off);
1.1 christos 1399: if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
1400: break;
1401: }
1402:
1403: /* set "current" pointer back to previous state */
1404: history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
1405:
1.11 lukem 1406: return (-1);
1.1 christos 1407: }
1408:
1409:
1410: /********************************/
1.40 christos 1411: /* completion functions */
1.1 christos 1412:
1.57 christos 1413: char *
1414: tilde_expand(char *name)
1415: {
1416: return fn_tilde_expand(name);
1417: }
1418:
1419: char *
1420: filename_completion_function(const char *name, int state)
1421: {
1422: return fn_filename_completion_function(name, state);
1423: }
1424:
1.1 christos 1425: /*
1426: * a completion generator for usernames; returns _first_ username
1427: * which starts with supplied text
1428: * text contains a partial username preceded by random character
1429: * (usually '~'); state is ignored
1430: * it's callers responsibility to free returned value
1431: */
1.11 lukem 1432: char *
1433: username_completion_function(const char *text, int state)
1.1 christos 1434: {
1.50 christos 1435: struct passwd *pwd, pwres;
1436: char pwbuf[1024];
1.1 christos 1437:
1438: if (text[0] == '\0')
1.11 lukem 1439: return (NULL);
1.1 christos 1440:
1441: if (*text == '~')
1442: text++;
1443:
1444: if (state == 0)
1445: setpwent();
1446:
1.50 christos 1447: while (getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pwd) == 0
1.52 christos 1448: && pwd != NULL && text[0] == pwd->pw_name[0]
1.11 lukem 1449: && strcmp(text, pwd->pw_name) == 0);
1.1 christos 1450:
1451: if (pwd == NULL) {
1452: endpwent();
1.11 lukem 1453: return (NULL);
1.1 christos 1454: }
1.11 lukem 1455: return (strdup(pwd->pw_name));
1.1 christos 1456: }
1457:
1.11 lukem 1458:
1.1 christos 1459: /*
1.46 christos 1460: * el-compatible wrapper to send TSTP on ^Z
1461: */
1462: /* ARGSUSED */
1463: static unsigned char
1464: _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
1465: {
1466: (void)kill(0, SIGTSTP);
1467: return CC_NORM;
1468: }
1.11 lukem 1469:
1.1 christos 1470: /*
1.12 jdolecek 1471: * Display list of strings in columnar format on readline's output stream.
1472: * 'matches' is list of strings, 'len' is number of strings in 'matches',
1473: * 'max' is maximum length of string in 'matches'.
1474: */
1475: void
1.53 dsl 1476: rl_display_match_list(char **matches, int len, int max)
1.12 jdolecek 1477: {
1478:
1.53 dsl 1479: fn_display_match_list(e, matches, len, max);
1.1 christos 1480: }
1481:
1.56 christos 1482: static const char *
1483: /*ARGSUSED*/
1484: _rl_completion_append_character_function(const char *dummy
1485: __attribute__((__unused__)))
1486: {
1487: static char buf[2];
1488: buf[1] = rl_completion_append_character;
1489: return buf;
1490: }
1491:
1.11 lukem 1492:
1.1 christos 1493: /*
1494: * complete word at current point
1495: */
1.53 dsl 1496: /* ARGSUSED */
1.1 christos 1497: int
1.53 dsl 1498: rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
1.1 christos 1499: {
1500: if (h == NULL || e == NULL)
1501: rl_initialize();
1502:
1503: if (rl_inhibit_completion) {
1.47 christos 1504: char arr[2];
1505: arr[0] = (char)invoking_key;
1506: arr[1] = '\0';
1507: el_insertstr(e, arr);
1.11 lukem 1508: return (CC_REFRESH);
1.53 dsl 1509: }
1510:
1511: /* Just look at how many global variables modify this operation! */
1512: return fn_complete(e,
1513: (CPFunction *)rl_completion_entry_function,
1514: rl_attempted_completion_function,
1515: rl_basic_word_break_characters, rl_special_prefixes,
1.56 christos 1516: _rl_completion_append_character_function, rl_completion_query_items,
1.53 dsl 1517: &rl_completion_type, &rl_attempted_completion_over,
1518: &rl_point, &rl_end);
1.1 christos 1519: }
1520:
1.11 lukem 1521:
1.53 dsl 1522: /* ARGSUSED */
1523: static unsigned char
1524: _el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
1525: {
1526: return (unsigned char)rl_complete(0, ch);
1527: }
1528:
1.1 christos 1529: /*
1.7 simonb 1530: * misc other functions
1.1 christos 1531: */
1532:
1533: /*
1534: * bind key c to readline-type function func
1535: */
1536: int
1.11 lukem 1537: rl_bind_key(int c, int func(int, int))
1.1 christos 1538: {
1.11 lukem 1539: int retval = -1;
1.1 christos 1540:
1541: if (h == NULL || e == NULL)
1542: rl_initialize();
1543:
1544: if (func == rl_insert) {
1545: /* XXX notice there is no range checking of ``c'' */
1546: e->el_map.key[c] = ED_INSERT;
1547: retval = 0;
1548: }
1.11 lukem 1549: return (retval);
1.1 christos 1550: }
1551:
1.11 lukem 1552:
1.1 christos 1553: /*
1554: * read one key from input - handles chars pushed back
1555: * to input stream also
1556: */
1557: int
1.11 lukem 1558: rl_read_key(void)
1.1 christos 1559: {
1.11 lukem 1560: char fooarr[2 * sizeof(int)];
1.1 christos 1561:
1562: if (e == NULL || h == NULL)
1563: rl_initialize();
1564:
1.11 lukem 1565: return (el_getc(e, fooarr));
1.1 christos 1566: }
1567:
1.11 lukem 1568:
1.1 christos 1569: /*
1570: * reset the terminal
1571: */
1.5 christos 1572: /* ARGSUSED */
1.1 christos 1573: void
1.30 christos 1574: rl_reset_terminal(const char *p __attribute__((__unused__)))
1.1 christos 1575: {
1.11 lukem 1576:
1.1 christos 1577: if (h == NULL || e == NULL)
1578: rl_initialize();
1579: el_reset(e);
1580: }
1581:
1.11 lukem 1582:
1.1 christos 1583: /*
1584: * insert character ``c'' back into input stream, ``count'' times
1585: */
1586: int
1.11 lukem 1587: rl_insert(int count, int c)
1.1 christos 1588: {
1.11 lukem 1589: char arr[2];
1.1 christos 1590:
1591: if (h == NULL || e == NULL)
1592: rl_initialize();
1593:
1594: /* XXX - int -> char conversion can lose on multichars */
1595: arr[0] = c;
1596: arr[1] = '\0';
1597:
1598: for (; count > 0; count--)
1599: el_push(e, arr);
1600:
1.11 lukem 1601: return (0);
1.35 christos 1602: }
1603:
1604: /*ARGSUSED*/
1605: int
1606: rl_newline(int count, int c)
1607: {
1608: /*
1609: * Readline-4.0 appears to ignore the args.
1610: */
1611: return rl_insert(1, '\n');
1612: }
1613:
1614: /*ARGSUSED*/
1615: static unsigned char
1616: rl_bind_wrapper(EditLine *el, unsigned char c)
1617: {
1618: if (map[c] == NULL)
1619: return CC_ERROR;
1.49 christos 1620:
1621: _rl_update_pos();
1622:
1.35 christos 1623: (*map[c])(NULL, c);
1.38 christos 1624:
1625: /* If rl_done was set by the above call, deal with it here */
1626: if (rl_done)
1627: return CC_EOF;
1628:
1.35 christos 1629: return CC_NORM;
1630: }
1631:
1632: int
1633: rl_add_defun(const char *name, Function *fun, int c)
1634: {
1635: char dest[8];
1636: if (c >= sizeof(map) / sizeof(map[0]) || c < 0)
1637: return -1;
1638: map[(unsigned char)c] = fun;
1639: el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
1.37 christos 1640: vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
1641: el_set(e, EL_BIND, dest, name);
1.35 christos 1642: return 0;
1643: }
1644:
1645: void
1646: rl_callback_read_char()
1647: {
1.36 christos 1648: int count = 0, done = 0;
1.35 christos 1649: const char *buf = el_gets(e, &count);
1650: char *wbuf;
1651:
1652: if (buf == NULL || count-- <= 0)
1653: return;
1.61 christos 1654: if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
1.36 christos 1655: done = 1;
1656: if (buf[count] == '\n' || buf[count] == '\r')
1657: done = 2;
1658:
1659: if (done && rl_linefunc != NULL) {
1.35 christos 1660: el_set(e, EL_UNBUFFERED, 0);
1.36 christos 1661: if (done == 2) {
1662: if ((wbuf = strdup(buf)) != NULL)
1663: wbuf[count] = '\0';
1664: } else
1665: wbuf = NULL;
1.35 christos 1666: (*(void (*)(const char *))rl_linefunc)(wbuf);
1.48 christos 1667: el_set(e, EL_UNBUFFERED, 1);
1.35 christos 1668: }
1669: }
1670:
1671: void
1.54 agc 1672: rl_callback_handler_install (const char *prompt, VCPFunction *linefunc)
1.35 christos 1673: {
1674: if (e == NULL) {
1675: rl_initialize();
1676: }
1677: if (rl_prompt)
1678: free(rl_prompt);
1679: rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL;
1680: rl_linefunc = linefunc;
1681: el_set(e, EL_UNBUFFERED, 1);
1682: }
1683:
1684: void
1685: rl_callback_handler_remove(void)
1686: {
1687: el_set(e, EL_UNBUFFERED, 0);
1688: }
1689:
1690: void
1691: rl_redisplay(void)
1692: {
1693: char a[2];
1.61 christos 1694: a[0] = e->el_tty.t_c[TS_IO][C_REPRINT];
1.35 christos 1695: a[1] = '\0';
1696: el_push(e, a);
1697: }
1698:
1699: int
1700: rl_get_previous_history(int count, int key)
1701: {
1702: char a[2];
1703: a[0] = key;
1704: a[1] = '\0';
1705: while (count--)
1706: el_push(e, a);
1707: return 0;
1.38 christos 1708: }
1709:
1710: void
1711: /*ARGSUSED*/
1712: rl_prep_terminal(int meta_flag)
1713: {
1714: el_set(e, EL_PREP_TERM, 1);
1715: }
1716:
1717: void
1718: rl_deprep_terminal()
1719: {
1720: el_set(e, EL_PREP_TERM, 0);
1721: }
1722:
1723: int
1724: rl_read_init_file(const char *s)
1725: {
1726: return(el_source(e, s));
1727: }
1728:
1729: int
1730: rl_parse_and_bind(const char *line)
1731: {
1732: const char **argv;
1733: int argc;
1734: Tokenizer *tok;
1735:
1736: tok = tok_init(NULL);
1.44 lukem 1737: tok_str(tok, line, &argc, &argv);
1.38 christos 1738: argc = el_parse(e, argc, argv);
1739: tok_end(tok);
1740: return (argc ? 1 : 0);
1741: }
1742:
1.51 christos 1743: int
1744: rl_variable_bind(const char *var, const char *value)
1745: {
1746: /*
1747: * The proper return value is undocument, but this is what the
1748: * readline source seems to do.
1749: */
1750: return ((el_set(e, EL_BIND, "", var, value) == -1) ? 1 : 0);
1751: }
1752:
1.38 christos 1753: void
1754: rl_stuff_char(int c)
1755: {
1756: char buf[2];
1757:
1758: buf[0] = c;
1759: buf[1] = '\0';
1760: el_insertstr(e, buf);
1761: }
1762:
1763: static int
1764: _rl_event_read_char(EditLine *el, char *cp)
1765: {
1.43 christos 1766: int n, num_read = 0;
1.38 christos 1767:
1768: *cp = 0;
1769: while (rl_event_hook) {
1770:
1771: (*rl_event_hook)();
1772:
1773: #if defined(FIONREAD)
1774: if (ioctl(el->el_infd, FIONREAD, &n) < 0)
1775: return(-1);
1776: if (n)
1777: num_read = read(el->el_infd, cp, 1);
1778: else
1779: num_read = 0;
1780: #elif defined(F_SETFL) && defined(O_NDELAY)
1781: if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
1782: return(-1);
1783: if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
1784: return(-1);
1785: num_read = read(el->el_infd, cp, 1);
1786: if (fcntl(el->el_infd, F_SETFL, n))
1787: return(-1);
1788: #else
1789: /* not non-blocking, but what you gonna do? */
1790: num_read = read(el->el_infd, cp, 1);
1791: return(-1);
1792: #endif
1793:
1794: if (num_read < 0 && errno == EAGAIN)
1795: continue;
1796: if (num_read == 0)
1797: continue;
1798: break;
1799: }
1800: if (!rl_event_hook)
1801: el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
1802: return(num_read);
1.1 christos 1803: }
1.49 christos 1804:
1805: static void
1806: _rl_update_pos(void)
1807: {
1808: const LineInfo *li = el_line(e);
1809:
1810: rl_point = li->cursor - li->buffer;
1811: rl_end = li->lastchar - li->buffer;
1812: }
CVSweb <webmaster@jp.NetBSD.org>