xref: /openbsd-src/gnu/lib/libreadline/util.c (revision af70c2df780099dcdde93deaba1af49686a47bbf)
11acd27e7Smillert /* util.c -- readline utility functions */
21acd27e7Smillert 
31acd27e7Smillert /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
41acd27e7Smillert 
51acd27e7Smillert    This file is part of the GNU Readline Library, a library for
61acd27e7Smillert    reading lines of text with interactive input and history editing.
71acd27e7Smillert 
81acd27e7Smillert    The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert    and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert    as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert    (at your option) any later version.
121acd27e7Smillert 
131acd27e7Smillert    The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161acd27e7Smillert    GNU General Public License for more details.
171acd27e7Smillert 
181acd27e7Smillert    The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert    is generally kept in a file called COPYING or LICENSE.  If you do not
201acd27e7Smillert    have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert 
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert #  include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert 
281acd27e7Smillert #include <sys/types.h>
291acd27e7Smillert #include <fcntl.h>
301acd27e7Smillert #include "posixjmp.h"
311acd27e7Smillert 
321acd27e7Smillert #if defined (HAVE_UNISTD_H)
331acd27e7Smillert #  include <unistd.h>           /* for _POSIX_VERSION */
341acd27e7Smillert #endif /* HAVE_UNISTD_H */
351acd27e7Smillert 
361acd27e7Smillert #if defined (HAVE_STDLIB_H)
371acd27e7Smillert #  include <stdlib.h>
381acd27e7Smillert #else
391acd27e7Smillert #  include "ansi_stdlib.h"
401acd27e7Smillert #endif /* HAVE_STDLIB_H */
411acd27e7Smillert 
421acd27e7Smillert #include <stdio.h>
431acd27e7Smillert #include <ctype.h>
441acd27e7Smillert 
451acd27e7Smillert /* System-specific feature definitions and include files. */
461acd27e7Smillert #include "rldefs.h"
471acd27e7Smillert 
481acd27e7Smillert #if defined (TIOCSTAT_IN_SYS_IOCTL)
491acd27e7Smillert #  include <sys/ioctl.h>
501acd27e7Smillert #endif /* TIOCSTAT_IN_SYS_IOCTL */
511acd27e7Smillert 
521acd27e7Smillert /* Some standard library routines. */
531acd27e7Smillert #include "readline.h"
541acd27e7Smillert 
551acd27e7Smillert #include "rlprivate.h"
561acd27e7Smillert #include "xmalloc.h"
571acd27e7Smillert 
581acd27e7Smillert /* **************************************************************** */
591acd27e7Smillert /*								    */
601acd27e7Smillert /*			Utility Functions			    */
611acd27e7Smillert /*								    */
621acd27e7Smillert /* **************************************************************** */
631acd27e7Smillert 
641acd27e7Smillert /* Return 0 if C is not a member of the class of characters that belong
651acd27e7Smillert    in words, or 1 if it is. */
661acd27e7Smillert 
671acd27e7Smillert int _rl_allow_pathname_alphabetic_chars = 0;
68*af70c2dfSkettenis static const char *pathname_alphabetic_chars = "/-_=~.#$";
691acd27e7Smillert 
701acd27e7Smillert int
rl_alphabetic(c)71*af70c2dfSkettenis rl_alphabetic (c)
721acd27e7Smillert      int c;
731acd27e7Smillert {
741acd27e7Smillert   if (ALPHABETIC (c))
751acd27e7Smillert     return (1);
761acd27e7Smillert 
771acd27e7Smillert   return (_rl_allow_pathname_alphabetic_chars &&
781acd27e7Smillert 	    strchr (pathname_alphabetic_chars, c) != NULL);
791acd27e7Smillert }
801acd27e7Smillert 
811acd27e7Smillert /* How to abort things. */
821acd27e7Smillert int
_rl_abort_internal()831acd27e7Smillert _rl_abort_internal ()
841acd27e7Smillert {
85*af70c2dfSkettenis   rl_ding ();
861acd27e7Smillert   rl_clear_message ();
871acd27e7Smillert   _rl_init_argument ();
88*af70c2dfSkettenis   rl_clear_pending_input ();
891acd27e7Smillert 
90*af70c2dfSkettenis   RL_UNSETSTATE (RL_STATE_MACRODEF);
91*af70c2dfSkettenis   while (rl_executing_macro)
921acd27e7Smillert     _rl_pop_executing_macro ();
931acd27e7Smillert 
94*af70c2dfSkettenis   rl_last_func = (rl_command_func_t *)NULL;
951acd27e7Smillert   longjmp (readline_top_level, 1);
961acd27e7Smillert   return (0);
971acd27e7Smillert }
981acd27e7Smillert 
991acd27e7Smillert int
rl_abort(count,key)1001acd27e7Smillert rl_abort (count, key)
1011acd27e7Smillert      int count, key;
1021acd27e7Smillert {
1031acd27e7Smillert   return (_rl_abort_internal ());
1041acd27e7Smillert }
1051acd27e7Smillert 
1061acd27e7Smillert int
rl_tty_status(count,key)1071acd27e7Smillert rl_tty_status (count, key)
1081acd27e7Smillert      int count, key;
1091acd27e7Smillert {
1101acd27e7Smillert #if defined (TIOCSTAT)
1111acd27e7Smillert   ioctl (1, TIOCSTAT, (char *)0);
1121acd27e7Smillert   rl_refresh_line (count, key);
1131acd27e7Smillert #else
114*af70c2dfSkettenis   rl_ding ();
1151acd27e7Smillert #endif
1161acd27e7Smillert   return 0;
1171acd27e7Smillert }
1181acd27e7Smillert 
1191acd27e7Smillert /* Return a copy of the string between FROM and TO.
1201acd27e7Smillert    FROM is inclusive, TO is not. */
1211acd27e7Smillert char *
rl_copy_text(from,to)1221acd27e7Smillert rl_copy_text (from, to)
1231acd27e7Smillert      int from, to;
1241acd27e7Smillert {
1251acd27e7Smillert   register int length;
1261acd27e7Smillert   char *copy;
1271acd27e7Smillert 
1281acd27e7Smillert   /* Fix it if the caller is confused. */
1291acd27e7Smillert   if (from > to)
1301acd27e7Smillert     SWAP (from, to);
1311acd27e7Smillert 
1321acd27e7Smillert   length = to - from;
133*af70c2dfSkettenis   copy = (char *)xmalloc (1 + length);
1341acd27e7Smillert   strncpy (copy, rl_line_buffer + from, length);
1351acd27e7Smillert   copy[length] = '\0';
1361acd27e7Smillert   return (copy);
1371acd27e7Smillert }
1381acd27e7Smillert 
1391acd27e7Smillert /* Increase the size of RL_LINE_BUFFER until it has enough space to hold
1401acd27e7Smillert    LEN characters. */
1411acd27e7Smillert void
rl_extend_line_buffer(len)1421acd27e7Smillert rl_extend_line_buffer (len)
1431acd27e7Smillert      int len;
1441acd27e7Smillert {
1451acd27e7Smillert   while (len >= rl_line_buffer_len)
1461acd27e7Smillert     {
1471acd27e7Smillert       rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
148*af70c2dfSkettenis       rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len);
1491acd27e7Smillert     }
1501acd27e7Smillert 
1511acd27e7Smillert   _rl_set_the_line ();
1521acd27e7Smillert }
1531acd27e7Smillert 
1541acd27e7Smillert 
1551acd27e7Smillert /* A function for simple tilde expansion. */
1561acd27e7Smillert int
rl_tilde_expand(ignore,key)1571acd27e7Smillert rl_tilde_expand (ignore, key)
1581acd27e7Smillert      int ignore, key;
1591acd27e7Smillert {
1601acd27e7Smillert   register int start, end;
1611acd27e7Smillert   char *homedir, *temp;
1621acd27e7Smillert   int len;
1631acd27e7Smillert 
1641acd27e7Smillert   end = rl_point;
1651acd27e7Smillert   start = end - 1;
1661acd27e7Smillert 
1671acd27e7Smillert   if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
1681acd27e7Smillert     {
1691acd27e7Smillert       homedir = tilde_expand ("~");
1701acd27e7Smillert       _rl_replace_text (homedir, start, end);
1711acd27e7Smillert       return (0);
1721acd27e7Smillert     }
1731acd27e7Smillert   else if (rl_line_buffer[start] != '~')
1741acd27e7Smillert     {
1751acd27e7Smillert       for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
1761acd27e7Smillert         ;
1771acd27e7Smillert       start++;
1781acd27e7Smillert     }
1791acd27e7Smillert 
1801acd27e7Smillert   end = start;
1811acd27e7Smillert   do
1821acd27e7Smillert     end++;
1831acd27e7Smillert   while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
1841acd27e7Smillert 
1851acd27e7Smillert   if (whitespace (rl_line_buffer[end]) || end >= rl_end)
1861acd27e7Smillert     end--;
1871acd27e7Smillert 
1881acd27e7Smillert   /* If the first character of the current word is a tilde, perform
1891acd27e7Smillert      tilde expansion and insert the result.  If not a tilde, do
1901acd27e7Smillert      nothing. */
1911acd27e7Smillert   if (rl_line_buffer[start] == '~')
1921acd27e7Smillert     {
1931acd27e7Smillert       len = end - start + 1;
194*af70c2dfSkettenis       temp = (char *)xmalloc (len + 1);
1951acd27e7Smillert       strncpy (temp, rl_line_buffer + start, len);
1961acd27e7Smillert       temp[len] = '\0';
1971acd27e7Smillert       homedir = tilde_expand (temp);
1981acd27e7Smillert       free (temp);
1991acd27e7Smillert 
2001acd27e7Smillert       _rl_replace_text (homedir, start, end);
2011acd27e7Smillert     }
2021acd27e7Smillert 
2031acd27e7Smillert   return (0);
2041acd27e7Smillert }
2051acd27e7Smillert 
2061acd27e7Smillert /* **************************************************************** */
2071acd27e7Smillert /*								    */
2081acd27e7Smillert /*			String Utility Functions		    */
2091acd27e7Smillert /*								    */
2101acd27e7Smillert /* **************************************************************** */
2111acd27e7Smillert 
2121acd27e7Smillert /* Determine if s2 occurs in s1.  If so, return a pointer to the
2131acd27e7Smillert    match in s1.  The compare is case insensitive. */
2141acd27e7Smillert char *
_rl_strindex(s1,s2)2151acd27e7Smillert _rl_strindex (s1, s2)
216*af70c2dfSkettenis      register const char *s1, *s2;
2171acd27e7Smillert {
2181acd27e7Smillert   register int i, l, len;
2191acd27e7Smillert 
2201acd27e7Smillert   for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
2211acd27e7Smillert     if (_rl_strnicmp (s1 + i, s2, l) == 0)
222*af70c2dfSkettenis       return ((char *) (s1 + i));
2231acd27e7Smillert   return ((char *)NULL);
2241acd27e7Smillert }
2251acd27e7Smillert 
226*af70c2dfSkettenis #ifndef HAVE_STRPBRK
227*af70c2dfSkettenis /* Find the first occurrence in STRING1 of any character from STRING2.
228*af70c2dfSkettenis    Return a pointer to the character in STRING1. */
229*af70c2dfSkettenis char *
_rl_strpbrk(string1,string2)230*af70c2dfSkettenis _rl_strpbrk (string1, string2)
231*af70c2dfSkettenis      const char *string1, *string2;
232*af70c2dfSkettenis {
233*af70c2dfSkettenis   register const char *scan;
234*af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
235*af70c2dfSkettenis   mbstate_t ps;
236*af70c2dfSkettenis   register int i, v;
237*af70c2dfSkettenis 
238*af70c2dfSkettenis   memset (&ps, 0, sizeof (mbstate_t));
239*af70c2dfSkettenis #endif
240*af70c2dfSkettenis 
241*af70c2dfSkettenis   for (; *string1; string1++)
242*af70c2dfSkettenis     {
243*af70c2dfSkettenis       for (scan = string2; *scan; scan++)
244*af70c2dfSkettenis 	{
245*af70c2dfSkettenis 	  if (*string1 == *scan)
246*af70c2dfSkettenis 	    return ((char *)string1);
247*af70c2dfSkettenis 	}
248*af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
249*af70c2dfSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
250*af70c2dfSkettenis 	{
251*af70c2dfSkettenis 	  v = _rl_get_char_len (string1, &ps);
252*af70c2dfSkettenis 	  if (v > 1)
253*af70c2dfSkettenis 	    string += v - 1;	/* -1 to account for auto-increment in loop */
254*af70c2dfSkettenis 	}
255*af70c2dfSkettenis #endif
256*af70c2dfSkettenis     }
257*af70c2dfSkettenis   return ((char *)NULL);
258*af70c2dfSkettenis }
259*af70c2dfSkettenis #endif
260*af70c2dfSkettenis 
2611acd27e7Smillert #if !defined (HAVE_STRCASECMP)
2621acd27e7Smillert /* Compare at most COUNT characters from string1 to string2.  Case
2631acd27e7Smillert    doesn't matter. */
2641acd27e7Smillert int
_rl_strnicmp(string1,string2,count)2651acd27e7Smillert _rl_strnicmp (string1, string2, count)
2661acd27e7Smillert      char *string1, *string2;
2671acd27e7Smillert      int count;
2681acd27e7Smillert {
2691acd27e7Smillert   register char ch1, ch2;
2701acd27e7Smillert 
2711acd27e7Smillert   while (count)
2721acd27e7Smillert     {
2731acd27e7Smillert       ch1 = *string1++;
2741acd27e7Smillert       ch2 = *string2++;
2751acd27e7Smillert       if (_rl_to_upper(ch1) == _rl_to_upper(ch2))
2761acd27e7Smillert 	count--;
2771acd27e7Smillert       else
2781acd27e7Smillert         break;
2791acd27e7Smillert     }
2801acd27e7Smillert   return (count);
2811acd27e7Smillert }
2821acd27e7Smillert 
2831acd27e7Smillert /* strcmp (), but caseless. */
2841acd27e7Smillert int
_rl_stricmp(string1,string2)2851acd27e7Smillert _rl_stricmp (string1, string2)
2861acd27e7Smillert      char *string1, *string2;
2871acd27e7Smillert {
2881acd27e7Smillert   register char ch1, ch2;
2891acd27e7Smillert 
2901acd27e7Smillert   while (*string1 && *string2)
2911acd27e7Smillert     {
2921acd27e7Smillert       ch1 = *string1++;
2931acd27e7Smillert       ch2 = *string2++;
2941acd27e7Smillert       if (_rl_to_upper(ch1) != _rl_to_upper(ch2))
2951acd27e7Smillert 	return (1);
2961acd27e7Smillert     }
2971acd27e7Smillert   return (*string1 - *string2);
2981acd27e7Smillert }
2991acd27e7Smillert #endif /* !HAVE_STRCASECMP */
3001acd27e7Smillert 
3011acd27e7Smillert /* Stupid comparison routine for qsort () ing strings. */
3021acd27e7Smillert int
_rl_qsort_string_compare(s1,s2)3031acd27e7Smillert _rl_qsort_string_compare (s1, s2)
3041acd27e7Smillert   char **s1, **s2;
3051acd27e7Smillert {
3061acd27e7Smillert #if defined (HAVE_STRCOLL)
3071acd27e7Smillert   return (strcoll (*s1, *s2));
3081acd27e7Smillert #else
3091acd27e7Smillert   int result;
3101acd27e7Smillert 
3111acd27e7Smillert   result = **s1 - **s2;
3121acd27e7Smillert   if (result == 0)
3131acd27e7Smillert     result = strcmp (*s1, *s2);
3141acd27e7Smillert 
3151acd27e7Smillert   return result;
3161acd27e7Smillert #endif
3171acd27e7Smillert }
3181acd27e7Smillert 
319*af70c2dfSkettenis /* Function equivalents for the macros defined in chardefs.h. */
320*af70c2dfSkettenis #define FUNCTION_FOR_MACRO(f)	int (f) (c) int c; { return f (c); }
3211acd27e7Smillert 
322*af70c2dfSkettenis FUNCTION_FOR_MACRO (_rl_digit_p)
323*af70c2dfSkettenis FUNCTION_FOR_MACRO (_rl_digit_value)
324*af70c2dfSkettenis FUNCTION_FOR_MACRO (_rl_lowercase_p)
325*af70c2dfSkettenis FUNCTION_FOR_MACRO (_rl_pure_alphabetic)
326*af70c2dfSkettenis FUNCTION_FOR_MACRO (_rl_to_lower)
327*af70c2dfSkettenis FUNCTION_FOR_MACRO (_rl_to_upper)
328*af70c2dfSkettenis FUNCTION_FOR_MACRO (_rl_uppercase_p)
3291acd27e7Smillert 
3301acd27e7Smillert /* Backwards compatibility, now that savestring has been removed from
3311acd27e7Smillert    all `public' readline header files. */
3321acd27e7Smillert #undef _rl_savestring
3331acd27e7Smillert char *
3341acd27e7Smillert _rl_savestring (s)
335*af70c2dfSkettenis      const char *s;
3361acd27e7Smillert {
33763bef317Sbeck 	char *cp;
33863bef317Sbeck 	cp = strdup(s);
33963bef317Sbeck 	if (cp == NULL)
34063bef317Sbeck 		memory_error_and_abort ("savestring");
34163bef317Sbeck 	return(cp);
3421acd27e7Smillert }
343