158314Sache/* $FreeBSD$ */
221308Sache/* util.c -- readline utility functions */
321308Sache
4157188Sache/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
521308Sache
621308Sache   This file is part of the GNU Readline Library, a library for
721308Sache   reading lines of text with interactive input and history editing.
821308Sache
921308Sache   The GNU Readline Library is free software; you can redistribute it
1021308Sache   and/or modify it under the terms of the GNU General Public License
1158314Sache   as published by the Free Software Foundation; either version 2, or
1221308Sache   (at your option) any later version.
1321308Sache
1421308Sache   The GNU Readline Library is distributed in the hope that it will be
1521308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1621308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1721308Sache   GNU General Public License for more details.
1821308Sache
1921308Sache   The GNU General Public License is often shipped with GNU software, and
2021308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2121308Sache   have a copy of the license, write to the Free Software Foundation,
2258314Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2321308Sache#define READLINE_LIBRARY
2421308Sache
2521308Sache#if defined (HAVE_CONFIG_H)
2621308Sache#  include <config.h>
2721308Sache#endif
2821308Sache
2921308Sache#include <sys/types.h>
3021308Sache#include <fcntl.h>
3126500Sache#include "posixjmp.h"
3221308Sache
3321308Sache#if defined (HAVE_UNISTD_H)
3421308Sache#  include <unistd.h>           /* for _POSIX_VERSION */
3521308Sache#endif /* HAVE_UNISTD_H */
3621308Sache
3721308Sache#if defined (HAVE_STDLIB_H)
3821308Sache#  include <stdlib.h>
3921308Sache#else
4021308Sache#  include "ansi_stdlib.h"
4121308Sache#endif /* HAVE_STDLIB_H */
4221308Sache
4326500Sache#include <stdio.h>
4426500Sache#include <ctype.h>
4526500Sache
4621308Sache/* System-specific feature definitions and include files. */
4721308Sache#include "rldefs.h"
48157188Sache#include "rlmbutil.h"
4921308Sache
5021308Sache#if defined (TIOCSTAT_IN_SYS_IOCTL)
5121308Sache#  include <sys/ioctl.h>
5221308Sache#endif /* TIOCSTAT_IN_SYS_IOCTL */
5321308Sache
5421308Sache/* Some standard library routines. */
5521308Sache#include "readline.h"
5621308Sache
5758314Sache#include "rlprivate.h"
5858314Sache#include "xmalloc.h"
5958314Sache
6021308Sache/* **************************************************************** */
6121308Sache/*								    */
6221308Sache/*			Utility Functions			    */
6321308Sache/*								    */
6421308Sache/* **************************************************************** */
6521308Sache
6621308Sache/* Return 0 if C is not a member of the class of characters that belong
6721308Sache   in words, or 1 if it is. */
6821308Sache
6921308Sacheint _rl_allow_pathname_alphabetic_chars = 0;
7075409Sachestatic const char *pathname_alphabetic_chars = "/-_=~.#$";
7121308Sache
7221308Sacheint
7375409Sacherl_alphabetic (c)
7421308Sache     int c;
7521308Sache{
7621308Sache  if (ALPHABETIC (c))
7721308Sache    return (1);
7821308Sache
7921308Sache  return (_rl_allow_pathname_alphabetic_chars &&
8021308Sache	    strchr (pathname_alphabetic_chars, c) != NULL);
8121308Sache}
8221308Sache
83157188Sache#if defined (HANDLE_MULTIBYTE)
84157188Sacheint
85157188Sache_rl_walphabetic (wc)
86157188Sache     wchar_t wc;
87157188Sache{
88157188Sache  int c;
89157188Sache
90157188Sache  if (iswalnum (wc))
91157188Sache    return (1);
92157188Sache
93157188Sache  c = wc & 0177;
94157188Sache  return (_rl_allow_pathname_alphabetic_chars &&
95157188Sache	    strchr (pathname_alphabetic_chars, c) != NULL);
96157188Sache}
97157188Sache#endif
98157188Sache
9921308Sache/* How to abort things. */
10021308Sacheint
10121308Sache_rl_abort_internal ()
10221308Sache{
10375409Sache  rl_ding ();
10421308Sache  rl_clear_message ();
105157188Sache  _rl_reset_argument ();
10675409Sache  rl_clear_pending_input ();
10721308Sache
108119614Sache  RL_UNSETSTATE (RL_STATE_MACRODEF);
10975409Sache  while (rl_executing_macro)
11021308Sache    _rl_pop_executing_macro ();
11121308Sache
11275409Sache  rl_last_func = (rl_command_func_t *)NULL;
11321308Sache  longjmp (readline_top_level, 1);
11421308Sache  return (0);
11521308Sache}
11621308Sache
11721308Sacheint
11821308Sacherl_abort (count, key)
11921308Sache     int count, key;
12021308Sache{
12121308Sache  return (_rl_abort_internal ());
12221308Sache}
12321308Sache
12421308Sacheint
12521308Sacherl_tty_status (count, key)
12621308Sache     int count, key;
12721308Sache{
12821308Sache#if defined (TIOCSTAT)
12921308Sache  ioctl (1, TIOCSTAT, (char *)0);
13047563Sache  rl_refresh_line (count, key);
13121308Sache#else
13275409Sache  rl_ding ();
13321308Sache#endif
13421308Sache  return 0;
13521308Sache}
13621308Sache
13721308Sache/* Return a copy of the string between FROM and TO.
13821308Sache   FROM is inclusive, TO is not. */
13921308Sachechar *
14021308Sacherl_copy_text (from, to)
14121308Sache     int from, to;
14221308Sache{
14321308Sache  register int length;
14421308Sache  char *copy;
14521308Sache
14621308Sache  /* Fix it if the caller is confused. */
14721308Sache  if (from > to)
14821308Sache    SWAP (from, to);
14921308Sache
15021308Sache  length = to - from;
151119614Sache  copy = (char *)xmalloc (1 + length);
15221308Sache  strncpy (copy, rl_line_buffer + from, length);
15321308Sache  copy[length] = '\0';
15421308Sache  return (copy);
15521308Sache}
15621308Sache
15721308Sache/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
15821308Sache   LEN characters. */
15921308Sachevoid
16021308Sacherl_extend_line_buffer (len)
16121308Sache     int len;
16221308Sache{
16321308Sache  while (len >= rl_line_buffer_len)
16421308Sache    {
16521308Sache      rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
166119614Sache      rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len);
16721308Sache    }
16821308Sache
16921308Sache  _rl_set_the_line ();
17021308Sache}
17121308Sache
17235489Sache
17335489Sache/* A function for simple tilde expansion. */
17435489Sacheint
17535489Sacherl_tilde_expand (ignore, key)
17635489Sache     int ignore, key;
17735489Sache{
17835489Sache  register int start, end;
17935489Sache  char *homedir, *temp;
18035489Sache  int len;
18135489Sache
18235489Sache  end = rl_point;
18335489Sache  start = end - 1;
18435489Sache
18535489Sache  if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
18635489Sache    {
18735489Sache      homedir = tilde_expand ("~");
18835489Sache      _rl_replace_text (homedir, start, end);
18935489Sache      return (0);
19035489Sache    }
19135489Sache  else if (rl_line_buffer[start] != '~')
19235489Sache    {
19335489Sache      for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
19435489Sache        ;
19535489Sache      start++;
19635489Sache    }
19735489Sache
19835489Sache  end = start;
19935489Sache  do
20035489Sache    end++;
20135489Sache  while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
20235489Sache
20335489Sache  if (whitespace (rl_line_buffer[end]) || end >= rl_end)
20435489Sache    end--;
20535489Sache
20635489Sache  /* If the first character of the current word is a tilde, perform
20735489Sache     tilde expansion and insert the result.  If not a tilde, do
20835489Sache     nothing. */
20935489Sache  if (rl_line_buffer[start] == '~')
21035489Sache    {
21135489Sache      len = end - start + 1;
212119614Sache      temp = (char *)xmalloc (len + 1);
21335489Sache      strncpy (temp, rl_line_buffer + start, len);
21435489Sache      temp[len] = '\0';
21535489Sache      homedir = tilde_expand (temp);
21635489Sache      free (temp);
21735489Sache
21835489Sache      _rl_replace_text (homedir, start, end);
21935489Sache    }
22035489Sache
22135489Sache  return (0);
22235489Sache}
22335489Sache
22421308Sache/* **************************************************************** */
22521308Sache/*								    */
22621308Sache/*			String Utility Functions		    */
22721308Sache/*								    */
22821308Sache/* **************************************************************** */
22921308Sache
23021308Sache/* Determine if s2 occurs in s1.  If so, return a pointer to the
23121308Sache   match in s1.  The compare is case insensitive. */
23221308Sachechar *
23321308Sache_rl_strindex (s1, s2)
23475409Sache     register const char *s1, *s2;
23521308Sache{
23621308Sache  register int i, l, len;
23721308Sache
23821308Sache  for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
23921308Sache    if (_rl_strnicmp (s1 + i, s2, l) == 0)
24075409Sache      return ((char *) (s1 + i));
24121308Sache  return ((char *)NULL);
24221308Sache}
24321308Sache
244119614Sache#ifndef HAVE_STRPBRK
24575409Sache/* Find the first occurrence in STRING1 of any character from STRING2.
24675409Sache   Return a pointer to the character in STRING1. */
24775409Sachechar *
24875409Sache_rl_strpbrk (string1, string2)
24975409Sache     const char *string1, *string2;
25075409Sache{
25175409Sache  register const char *scan;
252119614Sache#if defined (HANDLE_MULTIBYTE)
253119614Sache  mbstate_t ps;
254119614Sache  register int i, v;
25575409Sache
256119614Sache  memset (&ps, 0, sizeof (mbstate_t));
257119614Sache#endif
258119614Sache
25975409Sache  for (; *string1; string1++)
26075409Sache    {
26175409Sache      for (scan = string2; *scan; scan++)
26275409Sache	{
26375409Sache	  if (*string1 == *scan)
26475409Sache	    return ((char *)string1);
26575409Sache	}
266119614Sache#if defined (HANDLE_MULTIBYTE)
267119614Sache      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
268119614Sache	{
269119614Sache	  v = _rl_get_char_len (string1, &ps);
270119614Sache	  if (v > 1)
271136759Speter	    string1 += v - 1;	/* -1 to account for auto-increment in loop */
272119614Sache	}
273119614Sache#endif
27475409Sache    }
27575409Sache  return ((char *)NULL);
27675409Sache}
277119614Sache#endif
27875409Sache
27921308Sache#if !defined (HAVE_STRCASECMP)
28021308Sache/* Compare at most COUNT characters from string1 to string2.  Case
28121308Sache   doesn't matter. */
28221308Sacheint
28321308Sache_rl_strnicmp (string1, string2, count)
28421308Sache     char *string1, *string2;
28521308Sache     int count;
28621308Sache{
28721308Sache  register char ch1, ch2;
28821308Sache
28921308Sache  while (count)
29021308Sache    {
29121308Sache      ch1 = *string1++;
29221308Sache      ch2 = *string2++;
29321308Sache      if (_rl_to_upper(ch1) == _rl_to_upper(ch2))
29421308Sache	count--;
29521308Sache      else
29621308Sache        break;
29721308Sache    }
29821308Sache  return (count);
29921308Sache}
30021308Sache
30121308Sache/* strcmp (), but caseless. */
30221308Sacheint
30321308Sache_rl_stricmp (string1, string2)
30421308Sache     char *string1, *string2;
30521308Sache{
30621308Sache  register char ch1, ch2;
30721308Sache
30821308Sache  while (*string1 && *string2)
30921308Sache    {
31021308Sache      ch1 = *string1++;
31121308Sache      ch2 = *string2++;
31221308Sache      if (_rl_to_upper(ch1) != _rl_to_upper(ch2))
31321308Sache	return (1);
31421308Sache    }
31521308Sache  return (*string1 - *string2);
31621308Sache}
31721308Sache#endif /* !HAVE_STRCASECMP */
31821308Sache
31921308Sache/* Stupid comparison routine for qsort () ing strings. */
32021308Sacheint
32121308Sache_rl_qsort_string_compare (s1, s2)
32221308Sache  char **s1, **s2;
32321308Sache{
32421308Sache#if defined (HAVE_STRCOLL)
32521308Sache  return (strcoll (*s1, *s2));
32621308Sache#else
32721308Sache  int result;
32821308Sache
32921308Sache  result = **s1 - **s2;
33021308Sache  if (result == 0)
33121308Sache    result = strcmp (*s1, *s2);
33221308Sache
33321308Sache  return result;
33421308Sache#endif
33521308Sache}
33621308Sache
337119614Sache/* Function equivalents for the macros defined in chardefs.h. */
338119614Sache#define FUNCTION_FOR_MACRO(f)	int (f) (c) int c; { return f (c); }
33921308Sache
340119614SacheFUNCTION_FOR_MACRO (_rl_digit_p)
341119614SacheFUNCTION_FOR_MACRO (_rl_digit_value)
342119614SacheFUNCTION_FOR_MACRO (_rl_lowercase_p)
343119614SacheFUNCTION_FOR_MACRO (_rl_pure_alphabetic)
344119614SacheFUNCTION_FOR_MACRO (_rl_to_lower)
345119614SacheFUNCTION_FOR_MACRO (_rl_to_upper)
346119614SacheFUNCTION_FOR_MACRO (_rl_uppercase_p)
34721308Sache
34835489Sache/* Backwards compatibility, now that savestring has been removed from
34935489Sache   all `public' readline header files. */
35035489Sache#undef _rl_savestring
35135489Sachechar *
35235489Sache_rl_savestring (s)
35375409Sache     const char *s;
35435489Sache{
355119614Sache  return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s)));
35635489Sache}
357