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