diff --git a/readline/ChangeLog b/readline/ChangeLog index 4af8ea0760..0936de8b4a 100644 --- a/readline/ChangeLog +++ b/readline/ChangeLog @@ -1,3 +1,13 @@ +Fri Sep 29 15:19:23 1995 steve chamberlain + + Fixes for when the host WIN32, but not MSC. + * complete.c: Sometimes have pwd.h + * parens.c: WIN32 has similar restrictions to __GO32__. + * readline.c (__GO32__): Some of this moved into rldefs.h + * signals.c (__GO32__): Likewise. + * rldefs.h (MSDOS||WIN32) becomes MSDOS||MSC. + (WIN32&&!WIN32): New definitions. + Wed Sep 20 12:57:17 1995 Ian Lance Taylor * Makefile.in (maintainer-clean): New synonym for realclean. diff --git a/readline/complete.c b/readline/complete.c index 7b733a3e80..0a996a7424 100644 --- a/readline/complete.c +++ b/readline/complete.c @@ -22,7 +22,6 @@ #include "sysdep.h" #include -#include #include #if !defined (NO_SYS_FILE) # include @@ -36,7 +35,7 @@ extern int errno; /* These next are for filename completion. Perhaps this belongs in a different place. */ -#ifndef __MSDOS__ +#if !defined(__MSDOS__) && !defined(_MSC_VER) #include #endif /* __MSDOS__ */ #if defined (USG) && !defined (isc386) && !defined (sgi) @@ -46,18 +45,23 @@ extern struct passwd *getpwuid (), *getpwent (); extern struct passwd *getpwent (); #endif +/* Included by on some systems, but not SCO, so include it here. */ +#include + /* System-specific feature definitions and include files. */ #include "rldefs.h" /* Some standard library routines. */ #include "readline.h" -#if !defined (strchr) -extern char *strchr (); -#endif /* !strchr */ -#if !defined (strrchr) -extern char *strrchr (); -#endif /* !strrchr*/ +/* Possible values for do_replace in rl_complete_internal. */ +#define NO_MATCH 0 +#define SINGLE_MATCH 1 +#define MULT_MATCH 2 + +#if !defined (strchr) && !defined (__STDC__) +extern char *strchr (), *strrchr (); +#endif /* !strchr && !__STDC__ */ extern char *tilde_expand (); extern char *rl_copy_text (); @@ -66,6 +70,10 @@ extern Function *rl_last_func; extern int rl_editing_mode; extern int screenwidth; +/* Forward declarations for functions defined and used in this file. */ +char *filename_completion_function (); +char **completion_matches (); + static int compare_strings (); static char *rl_strpbrk (); @@ -86,6 +94,10 @@ int rl_complete_with_tilde_expansion = 0; #define VISIBLE_STATS #if defined (VISIBLE_STATS) +# if !defined (X_OK) +# define X_OK 1 +# endif + static int stat_char (); /* Non-zero means add an additional character to each filename displayed @@ -112,7 +124,7 @@ Function *rl_completion_entry_function = (Function *)NULL; If this function exists and returns NULL then call the value of rl_completion_entry_function to try to match, otherwise use the array of strings returned. */ -Function *rl_attempted_completion_function = (Function *)NULL; +CPPFunction *rl_attempted_completion_function = (CPPFunction *)NULL; /* Local variable states what happened during the last completion attempt. */ static int completion_changed_buffer = 0; @@ -132,6 +144,7 @@ rl_complete (ignore, invoking_key) /* List the possible completions. See description of rl_complete (). */ rl_possible_completions (ignore, invoking_key) + int ignore, invoking_key; { rl_complete_internal ('?'); } @@ -205,6 +218,44 @@ int rl_filename_completion_desired = 0; to implement FIGNORE a la SunOS csh. */ Function *rl_ignore_some_completions_function = (Function *)NULL; +#if defined (SHELL) +/* A function to strip quotes that are not protected by backquotes. It + allows single quotes to appear within double quotes, and vice versa. + It should be smarter. It's fairly shell-specific, hence the SHELL + definition wrapper. */ +static char * +_delete_quotes (text) + char *text; +{ + char *ret, *p, *r; + int l, quoted; + + l = strlen (text); + ret = xmalloc (l + 1); + for (quoted = 0, p = text, r = ret; p && *p; p++) + { + /* Allow backslash-quoted characters to pass through unscathed. */ + if (*p == '\\') + continue; + /* Close quote. */ + if (quoted && *p == quoted) + { + quoted = 0; + continue; + } + /* Open quote. */ + if (quoted == 0 && (*p == '\'' || *p == '"')) + { + quoted = *p; + continue; + } + *r++ = *p; + } + *r = '\0'; + return ret; +} +#endif /* SHELL */ + /* Complete the word at or before point. WHAT_TO_DO says what to do with the completion. `?' means list the possible completions. @@ -213,13 +264,15 @@ Function *rl_ignore_some_completions_function = (Function *)NULL; rl_complete_internal (what_to_do) int what_to_do; { - char *filename_completion_function (); - char **completion_matches (), **matches; + char **matches; Function *our_func; - int start, scan, end, delimiter = 0; + int start, scan, end, delimiter = 0, pass_next; char *text, *saved_line_buffer; - char quote_char = '\0'; char *replacement; + char quote_char = '\0'; +#if defined (SHELL) + int found_quote = 0; +#endif if (rl_line_buffer) saved_line_buffer = savestring (rl_line_buffer); @@ -229,7 +282,7 @@ rl_complete_internal (what_to_do) if (rl_completion_entry_function) our_func = rl_completion_entry_function; else - our_func = (int (*)())filename_completion_function; + our_func = (Function *)filename_completion_function; /* Only the completion entry function can change this. */ rl_filename_completion_desired = 0; @@ -243,16 +296,28 @@ rl_complete_internal (what_to_do) { /* We have a list of characters which can be used in pairs to quote substrings for the completer. Try to find the start - of an unclosed quoted substring. - [FIXME: Doesn't yet handle '\' escapes to quote quotes. */ - for (scan = 0; scan < end; scan++) + of an unclosed quoted substring. */ + /* FOUND_QUOTE is set so we know what kind of quotes we found. */ + for (scan = pass_next = 0; scan < end; scan++) { + if (pass_next) + { + pass_next = 0; + continue; + } + + if (rl_line_buffer[scan] == '\\') + { + pass_next = 1; + continue; + } + if (quote_char != '\0') { /* Ignore everything until the matching close quote char. */ if (rl_line_buffer[scan] == quote_char) { - /* Found matching close quote. Abandon this substring. */ + /* Found matching close. Abandon this substring. */ quote_char = '\0'; rl_point = end; } @@ -262,17 +327,41 @@ rl_complete_internal (what_to_do) /* Found start of a quoted substring. */ quote_char = rl_line_buffer[scan]; rl_point = scan + 1; +#if defined (SHELL) + if (quote_char == '\'') + found_quote |= 1; + else if (quote_char == '"') + found_quote |= 2; +#endif } } } + if (rl_point == end) { - /* We didn't find an unclosed quoted substring upon which to do + int quoted = 0; + /* We didn't find an unclosed quoted substring up which to do completion, so use the word break characters to find the - substring on which to do completion. */ - while (--rl_point && - !strchr (rl_completer_word_break_characters, - rl_line_buffer[rl_point])) {;} + substring on which to complete. */ + while (--rl_point) + { +#if defined (SHELL) + /* Don't let word break characters in quoted substrings break + words for the completer. */ + if (found_quote) + { + if (strchr (rl_completer_quote_characters, rl_line_buffer[rl_point])) + { + quoted = !quoted; + continue; + } + if (quoted) + continue; + } +#endif /* SHELL */ + if (strchr (rl_completer_word_break_characters, rl_line_buffer[rl_point])) + break; + } } /* If we are at a word break, then advance past it. */ @@ -285,13 +374,13 @@ rl_complete_internal (what_to_do) /* If the character isn't needed to determine something special about what kind of completion to perform, then advance past it. */ - if (!rl_special_prefixes || !strchr (rl_special_prefixes, rl_line_buffer[rl_point])) rl_point++; } } + /* At this point, we know we have an open quote if quote_char != '\0'. */ start = rl_point; rl_point = end; text = rl_copy_text (start, end); @@ -301,11 +390,11 @@ rl_complete_internal (what_to_do) variable rl_attempted_completion_function. */ if (rl_attempted_completion_function) { - matches = - (char **)(*rl_attempted_completion_function) (text, start, end); + matches = (*rl_attempted_completion_function) (text, start, end); if (matches) { + /* XXX - This is questionable code. - XXX */ if (matches == (char **)-1) matches = (char **)NULL; our_func = (Function *)NULL; @@ -313,6 +402,19 @@ rl_complete_internal (what_to_do) } } +#if defined (SHELL) + /* Beware -- we're stripping the quotes here. Do this only if we know + we are doing filename completion. */ + if (found_quote && our_func == (Function *)filename_completion_function) + { + /* delete single and double quotes */ + replacement = _delete_quotes (text); + free (text); + text = replacement; + replacement = (char *)0; + } +#endif /* SHELL */ + matches = completion_matches (text, our_func); after_usual_completion: @@ -324,15 +426,14 @@ rl_complete_internal (what_to_do) { register int i; - some_matches: - /* It seems to me that in all the cases we handle we would like - to ignore duplicate possibilities. Scan for the text to + to ignore duplicate possiblilities. Scan for the text to insert being identical to the other completions. */ if (rl_ignore_completion_duplicates) { char *lowest_common; int j, newlen = 0; + char dead_slot; /* Sort the items. */ /* It is safe to sort this array, because the lowest common @@ -348,13 +449,13 @@ rl_complete_internal (what_to_do) if (strcmp (matches[i], matches[i + 1]) == 0) { free (matches[i]); - matches[i] = (char *)-1; + matches[i] = (char *)&dead_slot; } else newlen++; } - /* We have marked all the dead slots with (char *)-1. + /* We have marked all the dead slots with (char *)&dead_slot. Copy all the non-dead entries into a new array. */ { char **temp_array = @@ -362,13 +463,13 @@ rl_complete_internal (what_to_do) for (i = 1, j = 1; matches[i]; i++) { - if (matches[i] != (char *)-1) + if (matches[i] != (char *)&dead_slot) temp_array[j++] = matches[i]; } temp_array[j] = (char *)NULL; - if (matches[0] != (char *)-1) + if (matches[0] != (char *)&dead_slot) free (matches[0]); free (matches); @@ -397,7 +498,7 @@ rl_complete_internal (what_to_do) ignore function with the array as a parameter. It can munge the array, deleting matches as it desires. */ if (rl_ignore_some_completions_function && - our_func == (int (*)())filename_completion_function) + our_func == (Function *)filename_completion_function) (void)(*rl_ignore_some_completions_function)(matches); /* If we are doing completion on quoted substrings, and any matches @@ -415,34 +516,45 @@ rl_complete_internal (what_to_do) { int do_replace; - do_replace = 0; + do_replace = NO_MATCH; - /* If there is only a single match, see if we need to - quote it. */ - if (!matches[1] && - rl_strpbrk (matches[0], rl_completer_word_break_characters)) - do_replace = 1; + /* If there is a single match, see if we need to quote it. + This also checks whether the common prefix of several + matches needs to be quoted. If the common prefix should + not be checked, add !matches[1] to the if clause. */ + if (rl_strpbrk (matches[0], rl_completer_word_break_characters)) + do_replace = matches[1] ? MULT_MATCH : SINGLE_MATCH; - /* If there are multiple matches, check to see if any of them - require that the substring be quoted. */ - for (i = 1; matches[i] != NULL; i++) - if (rl_strpbrk (matches[i], rl_completer_word_break_characters)) - { - do_replace = 1; - break; - } - if (do_replace) + if (do_replace != NO_MATCH) { #if defined (SHELL) /* XXX - experimental */ - /* Single-quote the replacement, since we found an - embedded word break character in a potential match. */ - char *rtext; - extern char *single_quote (); /* in builtins/common.c */ + /* Quote the replacement, since we found an + embedded word break character in a potential + match. */ + char *rtext, *mtext; + int rlen; + extern char *double_quote (); /* in builtins/common.c */ - rtext = single_quote (matches[0]); - replacement = (char *)alloca (strlen (rtext) + 1); + /* If DO_REPLACE == MULT_MATCH, it means that there is + more than one match. In this case, we do not add + the closing quote or attempt to perform tilde + expansion. If DO_REPLACE == SINGLE_MATCH, we try + to perform tilde expansion, because double quotes + inhibit tilde expansion by the shell. */ + + mtext = matches[0]; + if (mtext[0] == '~' && do_replace == SINGLE_MATCH) + mtext = tilde_expand (matches[0]); + rtext = double_quote (mtext); + if (mtext != matches[0]) + free (mtext); + + rlen = strlen (rtext); + replacement = (char *)alloca (rlen + 1); strcpy (replacement, rtext); + if (do_replace == MULT_MATCH) + replacement[rlen - 1] = '\0'; free (rtext); #else /* !SHELL */ /* Found an embedded word break character in a potential @@ -455,6 +567,7 @@ rl_complete_internal (what_to_do) #endif /* SHELL */ } } + if (replacement) { rl_delete_text (start, rl_point); @@ -541,12 +654,10 @@ rl_complete_internal (what_to_do) /* Handle simple case first. What if there is only one answer? */ if (!matches[1]) { - char *temp; + char *temp = (char *)NULL; if (rl_filename_completion_desired) temp = strrchr (matches[0], '/'); - else - temp = (char *)NULL; if (!temp) temp = matches[0]; @@ -613,6 +724,7 @@ rl_complete_internal (what_to_do) goto restart; } } + /* How many items of MAX length can we fit in the screen window? */ max += 2; limit = screenwidth / max; @@ -697,6 +809,7 @@ rl_complete_internal (what_to_do) break; default: + fprintf (stderr, "\r\nreadline: bad value for what_to_do in rl_complete\n"); abort (); } @@ -768,9 +881,9 @@ username_completion_function (text, state) int state; char *text; { -#ifdef __GO32__ +#if defined (MINIMAL) return (char *)NULL; -#else /* !__GO32__ */ +#else /* !MINIMAL */ static char *username = (char *)NULL; static struct passwd *entry; static int namelen, first_char, first_char_loc; @@ -816,9 +929,8 @@ username_completion_function (text, state) return (value); } -#endif /* !__GO32__ */ +#endif /* !MINIMAL */ } - /* **************************************************************** */ /* */ @@ -844,7 +956,7 @@ int completion_case_fold = 0; char ** completion_matches (text, entry_function) char *text; - char *(*entry_function) (); + CPFunction *entry_function; { /* Number of slots in match_list. */ int match_list_size; @@ -935,6 +1047,7 @@ filename_completion_function (text, state) int state; char *text; { +#ifndef WIN32 static DIR *directory; static char *filename = (char *)NULL; static char *dirname = (char *)NULL; @@ -1077,6 +1190,7 @@ filename_completion_function (text, state) } return (temp); } +#endif } /* A function for simple tilde expansion. */ diff --git a/readline/signals.c b/readline/signals.c new file mode 100644 index 0000000000..35a64b6f28 --- /dev/null +++ b/readline/signals.c @@ -0,0 +1,248 @@ +/* signals.c -- signal handling support for readline. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 1, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#if !defined (NO_SYS_FILE) +# include +#endif /* !NO_SYS_FILE */ +#include + +/* This is needed to include support for TIOCGWINSZ and window resizing. */ +#if defined (OSF1) || defined (BSD386) || defined (_386BSD) || defined (__BSD_4_4__) || defined (AIX) +# include +#endif /* OSF1 || BSD386 || _386BSD || __BSD_4_4__ || AIX */ + +#include +/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +static void cr (); + +extern int readline_echoing_p; +extern int rl_pending_input; + +extern int _rl_meta_flag; + +#ifdef __STDC__ +extern void _rl_output_character_function (int); +#else +extern void _rl_output_character_function (); +#endif + +extern void free_undo_list (); + +#if defined (VOID_SIGHANDLER) +# define sighandler void +#else +# define sighandler int +#endif /* VOID_SIGHANDLER */ + +/* This typedef is equivalant to the one for Function; it allows us + to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ +typedef sighandler SigHandler (); + +/* **************************************************************** */ +/* */ +/* Signal Handling */ +/* */ +/* **************************************************************** */ + +#if defined (HANDLE_SIGNALS) + +#if defined (SIGWINCH) +static SigHandler *old_sigwinch = (SigHandler *)NULL; + +static sighandler +rl_handle_sigwinch (sig) + int sig; +{ + if (readline_echoing_p) + { + _rl_set_screen_size (fileno (rl_instream), 1); + + cr (); /* was crlf () */ + rl_forced_update_display (); + } + + if (old_sigwinch && + old_sigwinch != (SigHandler *)SIG_IGN && + old_sigwinch != (SigHandler *)SIG_DFL) + (*old_sigwinch) (sig); +#if !defined (VOID_SIGHANDLER) + return (0); +#endif /* VOID_SIGHANDLER */ +} +#endif /* SIGWINCH */ + +/* Interrupt handling. */ +static SigHandler + *old_int = (SigHandler *)NULL, + *old_tstp = (SigHandler *)NULL, + *old_ttou = (SigHandler *)NULL, + *old_ttin = (SigHandler *)NULL, + *old_cont = (SigHandler *)NULL, + *old_alrm = (SigHandler *)NULL; + +/* Handle an interrupt character. */ +static sighandler +rl_signal_handler (sig) + int sig; +{ +#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) + /* Since the signal will not be blocked while we are in the signal + handler, ignore it until rl_clear_signals resets the catcher. */ + if (sig == SIGINT) + signal (sig, SIG_IGN); +#endif /* !HAVE_BSD_SIGNALS */ + + switch (sig) + { + case SIGINT: + { + register HIST_ENTRY *entry; + + free_undo_list (); + + entry = current_history (); + if (entry) + entry->data = (char *)NULL; + } + _rl_kill_kbd_macro (); + rl_clear_message (); + rl_init_argument (); + +#if defined (SIGTSTP) + case SIGTSTP: + case SIGTTOU: + case SIGTTIN: +#endif /* SIGTSTP */ + case SIGALRM: + rl_clean_up_for_exit (); + rl_deprep_terminal (); + rl_clear_signals (); + rl_pending_input = 0; + + kill (getpid (), sig); + + SIGNALS_UNBLOCK; + + rl_prep_terminal (_rl_meta_flag); + rl_set_signals (); + } + +#if !defined (VOID_SIGHANDLER) + return (0); +#endif /* !VOID_SIGHANDLER */ +} + +#if defined (HAVE_POSIX_SIGNALS) +static SigHandler * +rl_set_sighandler (sig, handler) + int sig; + SigHandler *handler; +{ + struct sigaction act, oact; + + act.sa_handler = handler; + act.sa_flags = 0; + sigemptyset (&act.sa_mask); + sigemptyset (&oact.sa_mask); + sigaction (sig, &act, &oact); + return (oact.sa_handler); +} + +#else /* !HAVE_POSIX_SIGNALS */ +# define rl_set_sighandler(sig, handler) (SigHandler *)signal (sig, handler) +#endif /* !HAVE_POSIX_SIGNALS */ + +rl_set_signals () +{ + old_int = (SigHandler *)rl_set_sighandler (SIGINT, rl_signal_handler); + if (old_int == (SigHandler *)SIG_IGN) + signal (SIGINT, SIG_IGN); + + old_alrm = (SigHandler *)rl_set_sighandler (SIGALRM, rl_signal_handler); + if (old_alrm == (SigHandler *)SIG_IGN) + signal (SIGALRM, SIG_IGN); + +#if defined (SIGTSTP) + old_tstp = (SigHandler *)rl_set_sighandler (SIGTSTP, rl_signal_handler); + if (old_tstp == (SigHandler *)SIG_IGN) + signal (SIGTSTP, SIG_IGN); +#endif +#if defined (SIGTTOU) + old_ttou = (SigHandler *)rl_set_sighandler (SIGTTOU, rl_signal_handler); + old_ttin = (SigHandler *)rl_set_sighandler (SIGTTIN, rl_signal_handler); + + if (old_tstp == (SigHandler *)SIG_IGN) + { + signal (SIGTTOU, SIG_IGN); + signal (SIGTTIN, SIG_IGN); + } +#endif + +#if defined (SIGWINCH) + old_sigwinch = + (SigHandler *) rl_set_sighandler (SIGWINCH, rl_handle_sigwinch); +#endif +} + +rl_clear_signals () +{ + rl_set_sighandler (SIGINT, old_int); + rl_set_sighandler (SIGALRM, old_alrm); + +#if defined (SIGTSTP) + signal (SIGTSTP, old_tstp); +#endif + +#if defined (SIGTTOU) + signal (SIGTTOU, old_ttou); + signal (SIGTTIN, old_ttin); +#endif + +#if defined (SIGWINCH) + signal (SIGWINCH, old_sigwinch); +#endif +} + +/* Move to the start of the current line. */ +static void +cr () +{ + extern char *term_cr; + + if (term_cr) + tputs (term_cr, 1, _rl_output_character_function); +} +#endif /* HANDLE_SIGNALS */