| /* util.c -- readline utility functions */ |
| |
| /* 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. */ |
| #define READLINE_LIBRARY |
| |
| #if defined (HAVE_CONFIG_H) |
| # include <config.h> |
| #endif |
| |
| #include <sys/types.h> |
| #include <fcntl.h> |
| #include "posixjmp.h" |
| |
| #if defined (HAVE_UNISTD_H) |
| # include <unistd.h> /* for _POSIX_VERSION */ |
| #endif /* HAVE_UNISTD_H */ |
| |
| #if defined (HAVE_STDLIB_H) |
| # include <stdlib.h> |
| #else |
| # include "ansi_stdlib.h" |
| #endif /* HAVE_STDLIB_H */ |
| |
| #include <stdio.h> |
| #include <ctype.h> |
| |
| /* System-specific feature definitions and include files. */ |
| #include "rldefs.h" |
| |
| #if defined (TIOCSTAT_IN_SYS_IOCTL) |
| # include <sys/ioctl.h> |
| #endif /* TIOCSTAT_IN_SYS_IOCTL */ |
| |
| /* Some standard library routines. */ |
| #include "readline.h" |
| |
| #define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) |
| |
| /* Pseudo-globals imported from readline.c */ |
| extern int readline_echoing_p; |
| extern procenv_t readline_top_level; |
| extern int rl_line_buffer_len; |
| extern Function *rl_last_func; |
| |
| extern int _rl_defining_kbd_macro; |
| extern char *_rl_executing_macro; |
| |
| /* Pseudo-global functions imported from other library files. */ |
| extern void _rl_pop_executing_macro (); |
| extern void _rl_set_the_line (); |
| extern void _rl_init_argument (); |
| |
| extern char *xmalloc (), *xrealloc (); |
| |
| /* **************************************************************** */ |
| /* */ |
| /* Utility Functions */ |
| /* */ |
| /* **************************************************************** */ |
| |
| /* Return 0 if C is not a member of the class of characters that belong |
| in words, or 1 if it is. */ |
| |
| int _rl_allow_pathname_alphabetic_chars = 0; |
| static char *pathname_alphabetic_chars = "/-_=~.#$"; |
| |
| int |
| alphabetic (c) |
| int c; |
| { |
| if (ALPHABETIC (c)) |
| return (1); |
| |
| return (_rl_allow_pathname_alphabetic_chars && |
| strchr (pathname_alphabetic_chars, c) != NULL); |
| } |
| |
| /* How to abort things. */ |
| int |
| _rl_abort_internal () |
| { |
| ding (); |
| rl_clear_message (); |
| _rl_init_argument (); |
| rl_pending_input = 0; |
| |
| _rl_defining_kbd_macro = 0; |
| while (_rl_executing_macro) |
| _rl_pop_executing_macro (); |
| |
| rl_last_func = (Function *)NULL; |
| longjmp (readline_top_level, 1); |
| return (0); |
| } |
| |
| int |
| rl_abort (count, key) |
| int count, key; |
| { |
| return (_rl_abort_internal ()); |
| } |
| |
| int |
| rl_tty_status (count, key) |
| int count, key; |
| { |
| #if defined (TIOCSTAT) |
| ioctl (1, TIOCSTAT, (char *)0); |
| rl_refresh_line (); |
| #else |
| ding (); |
| #endif |
| return 0; |
| } |
| |
| /* Return a copy of the string between FROM and TO. |
| FROM is inclusive, TO is not. */ |
| char * |
| rl_copy_text (from, to) |
| int from, to; |
| { |
| register int length; |
| char *copy; |
| |
| /* Fix it if the caller is confused. */ |
| if (from > to) |
| SWAP (from, to); |
| |
| length = to - from; |
| copy = xmalloc (1 + length); |
| strncpy (copy, rl_line_buffer + from, length); |
| copy[length] = '\0'; |
| return (copy); |
| } |
| |
| /* Increase the size of RL_LINE_BUFFER until it has enough space to hold |
| LEN characters. */ |
| void |
| rl_extend_line_buffer (len) |
| int len; |
| { |
| while (len >= rl_line_buffer_len) |
| { |
| rl_line_buffer_len += DEFAULT_BUFFER_SIZE; |
| rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len); |
| } |
| |
| _rl_set_the_line (); |
| } |
| |
| |
| /* A function for simple tilde expansion. */ |
| int |
| rl_tilde_expand (ignore, key) |
| int ignore, key; |
| { |
| register int start, end; |
| char *homedir, *temp; |
| int len; |
| |
| end = rl_point; |
| start = end - 1; |
| |
| if (rl_point == rl_end && rl_line_buffer[rl_point] == '~') |
| { |
| homedir = tilde_expand ("~"); |
| _rl_replace_text (homedir, start, end); |
| return (0); |
| } |
| else if (rl_line_buffer[start] != '~') |
| { |
| for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--) |
| ; |
| start++; |
| } |
| |
| end = start; |
| do |
| end++; |
| while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end); |
| |
| if (whitespace (rl_line_buffer[end]) || end >= rl_end) |
| end--; |
| |
| /* If the first character of the current word is a tilde, perform |
| tilde expansion and insert the result. If not a tilde, do |
| nothing. */ |
| if (rl_line_buffer[start] == '~') |
| { |
| len = end - start + 1; |
| temp = xmalloc (len + 1); |
| strncpy (temp, rl_line_buffer + start, len); |
| temp[len] = '\0'; |
| homedir = tilde_expand (temp); |
| free (temp); |
| |
| _rl_replace_text (homedir, start, end); |
| } |
| |
| return (0); |
| } |
| |
| /* **************************************************************** */ |
| /* */ |
| /* String Utility Functions */ |
| /* */ |
| /* **************************************************************** */ |
| |
| /* Determine if s2 occurs in s1. If so, return a pointer to the |
| match in s1. The compare is case insensitive. */ |
| char * |
| _rl_strindex (s1, s2) |
| register char *s1, *s2; |
| { |
| register int i, l, len; |
| |
| for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++) |
| if (_rl_strnicmp (s1 + i, s2, l) == 0) |
| return (s1 + i); |
| return ((char *)NULL); |
| } |
| |
| #if !defined (HAVE_STRCASECMP) |
| /* Compare at most COUNT characters from string1 to string2. Case |
| doesn't matter. */ |
| int |
| _rl_strnicmp (string1, string2, count) |
| char *string1, *string2; |
| int count; |
| { |
| register char ch1, ch2; |
| |
| while (count) |
| { |
| ch1 = *string1++; |
| ch2 = *string2++; |
| if (_rl_to_upper(ch1) == _rl_to_upper(ch2)) |
| count--; |
| else |
| break; |
| } |
| return (count); |
| } |
| |
| /* strcmp (), but caseless. */ |
| int |
| _rl_stricmp (string1, string2) |
| char *string1, *string2; |
| { |
| register char ch1, ch2; |
| |
| while (*string1 && *string2) |
| { |
| ch1 = *string1++; |
| ch2 = *string2++; |
| if (_rl_to_upper(ch1) != _rl_to_upper(ch2)) |
| return (1); |
| } |
| return (*string1 - *string2); |
| } |
| #endif /* !HAVE_STRCASECMP */ |
| |
| /* Stupid comparison routine for qsort () ing strings. */ |
| int |
| _rl_qsort_string_compare (s1, s2) |
| char **s1, **s2; |
| { |
| #if defined (HAVE_STRCOLL) |
| return (strcoll (*s1, *s2)); |
| #else |
| int result; |
| |
| result = **s1 - **s2; |
| if (result == 0) |
| result = strcmp (*s1, *s2); |
| |
| return result; |
| #endif |
| } |
| |
| /* Function equivalents for the macros defined in chartypes.h. */ |
| #undef _rl_uppercase_p |
| int |
| _rl_uppercase_p (c) |
| int c; |
| { |
| return (isupper (c)); |
| } |
| |
| #undef _rl_lowercase_p |
| int |
| _rl_lowercase_p (c) |
| int c; |
| { |
| return (islower (c)); |
| } |
| |
| #undef _rl_pure_alphabetic |
| int |
| _rl_pure_alphabetic (c) |
| int c; |
| { |
| return (isupper (c) || islower (c)); |
| } |
| |
| #undef _rl_digit_p |
| int |
| _rl_digit_p (c) |
| int c; |
| { |
| return (isdigit (c)); |
| } |
| |
| #undef _rl_to_lower |
| int |
| _rl_to_lower (c) |
| int c; |
| { |
| return (isupper (c) ? tolower (c) : c); |
| } |
| |
| #undef _rl_to_upper |
| int |
| _rl_to_upper (c) |
| int c; |
| { |
| return (islower (c) ? toupper (c) : c); |
| } |
| |
| #undef _rl_digit_value |
| int |
| _rl_digit_value (c) |
| int c; |
| { |
| return (isdigit (c) ? c - '0' : c); |
| } |
| |
| /* Backwards compatibility, now that savestring has been removed from |
| all `public' readline header files. */ |
| #undef _rl_savestring |
| char * |
| _rl_savestring (s) |
| char *s; |
| { |
| return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s))); |
| } |