1/* util.c -- readline utility functions */
2
3/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
4
5   This file is part of the GNU Readline Library, a library for
6   reading lines of text with interactive input and history editing.
7
8   The GNU Readline Library is free software; you can redistribute it
9   and/or modify it under the terms of the GNU General Public License
10   as published by the Free Software Foundation; either version 2, or
11   (at your option) any later version.
12
13   The GNU Readline Library is distributed in the hope that it will be
14   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   The GNU General Public License is often shipped with GNU software, and
19   is generally kept in a file called COPYING or LICENSE.  If you do not
20   have a copy of the license, write to the Free Software Foundation,
21   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22#define READLINE_LIBRARY
23
24#if defined (HAVE_CONFIG_H)
25#  include <config.h>
26#endif
27
28#include <sys/types.h>
29#include <fcntl.h>
30#include "posixjmp.h"
31
32#if defined (HAVE_UNISTD_H)
33#  include <unistd.h>           /* for _POSIX_VERSION */
34#endif /* HAVE_UNISTD_H */
35
36#if defined (HAVE_STDLIB_H)
37#  include <stdlib.h>
38#else
39#  include "ansi_stdlib.h"
40#endif /* HAVE_STDLIB_H */
41
42#include <stdio.h>
43#include <ctype.h>
44
45/* System-specific feature definitions and include files. */
46#include "rldefs.h"
47
48#if defined (TIOCSTAT_IN_SYS_IOCTL)
49#  include <sys/ioctl.h>
50#endif /* TIOCSTAT_IN_SYS_IOCTL */
51
52/* Some standard library routines. */
53#include "readline.h"
54
55#include "rlprivate.h"
56#include "xmalloc.h"
57
58/* **************************************************************** */
59/*								    */
60/*			Utility Functions			    */
61/*								    */
62/* **************************************************************** */
63
64/* Return 0 if C is not a member of the class of characters that belong
65   in words, or 1 if it is. */
66
67int _rl_allow_pathname_alphabetic_chars = 0;
68static const char *pathname_alphabetic_chars = "/-_=~.#$";
69
70int
71rl_alphabetic (c)
72     int c;
73{
74  if (ALPHABETIC (c))
75    return (1);
76
77  return (_rl_allow_pathname_alphabetic_chars &&
78	    strchr (pathname_alphabetic_chars, c) != NULL);
79}
80
81/* How to abort things. */
82int
83_rl_abort_internal ()
84{
85  rl_ding ();
86  rl_clear_message ();
87  _rl_init_argument ();
88  rl_clear_pending_input ();
89
90  RL_UNSETSTATE (RL_STATE_MACRODEF);
91  while (rl_executing_macro)
92    _rl_pop_executing_macro ();
93
94  rl_last_func = (rl_command_func_t *)NULL;
95  longjmp (readline_top_level, 1);
96  return (0);
97}
98
99int
100rl_abort (count, key)
101     int count, key;
102{
103  return (_rl_abort_internal ());
104}
105
106int
107rl_tty_status (count, key)
108     int count, key;
109{
110#if defined (TIOCSTAT)
111  ioctl (1, TIOCSTAT, (char *)0);
112  rl_refresh_line (count, key);
113#else
114  rl_ding ();
115#endif
116  return 0;
117}
118
119/* Return a copy of the string between FROM and TO.
120   FROM is inclusive, TO is not. */
121char *
122rl_copy_text (from, to)
123     int from, to;
124{
125  register int length;
126  char *copy;
127
128  /* Fix it if the caller is confused. */
129  if (from > to)
130    SWAP (from, to);
131
132  length = to - from;
133  copy = (char *)xmalloc (1 + length);
134  strncpy (copy, rl_line_buffer + from, length);
135  copy[length] = '\0';
136  return (copy);
137}
138
139/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
140   LEN characters. */
141void
142rl_extend_line_buffer (len)
143     int len;
144{
145  while (len >= rl_line_buffer_len)
146    {
147      rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
148      rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len);
149    }
150
151  _rl_set_the_line ();
152}
153
154
155/* A function for simple tilde expansion. */
156int
157rl_tilde_expand (ignore, key)
158     int ignore, key;
159{
160  register int start, end;
161  char *homedir, *temp;
162  int len;
163
164  end = rl_point;
165  start = end - 1;
166
167  if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
168    {
169      homedir = tilde_expand ("~");
170      _rl_replace_text (homedir, start, end);
171      return (0);
172    }
173  else if (rl_line_buffer[start] != '~')
174    {
175      for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
176        ;
177      start++;
178    }
179
180  end = start;
181  do
182    end++;
183  while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
184
185  if (whitespace (rl_line_buffer[end]) || end >= rl_end)
186    end--;
187
188  /* If the first character of the current word is a tilde, perform
189     tilde expansion and insert the result.  If not a tilde, do
190     nothing. */
191  if (rl_line_buffer[start] == '~')
192    {
193      len = end - start + 1;
194      temp = (char *)xmalloc (len + 1);
195      strncpy (temp, rl_line_buffer + start, len);
196      temp[len] = '\0';
197      homedir = tilde_expand (temp);
198      free (temp);
199
200      _rl_replace_text (homedir, start, end);
201    }
202
203  return (0);
204}
205
206/* **************************************************************** */
207/*								    */
208/*			String Utility Functions		    */
209/*								    */
210/* **************************************************************** */
211
212/* Determine if s2 occurs in s1.  If so, return a pointer to the
213   match in s1.  The compare is case insensitive. */
214char *
215_rl_strindex (s1, s2)
216     register const char *s1, *s2;
217{
218  register int i, l, len;
219
220  for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
221    if (_rl_strnicmp (s1 + i, s2, l) == 0)
222      return ((char *) (s1 + i));
223  return ((char *)NULL);
224}
225
226#ifndef HAVE_STRPBRK
227/* Find the first occurrence in STRING1 of any character from STRING2.
228   Return a pointer to the character in STRING1. */
229char *
230_rl_strpbrk (string1, string2)
231     const char *string1, *string2;
232{
233  register const char *scan;
234#if defined (HANDLE_MULTIBYTE)
235  mbstate_t ps;
236  register int i, v;
237
238  memset (&ps, 0, sizeof (mbstate_t));
239#endif
240
241  for (; *string1; string1++)
242    {
243      for (scan = string2; *scan; scan++)
244	{
245	  if (*string1 == *scan)
246	    return ((char *)string1);
247	}
248#if defined (HANDLE_MULTIBYTE)
249      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
250	{
251	  v = _rl_get_char_len (string1, &ps);
252	  if (v > 1)
253	    string += v - 1;	/* -1 to account for auto-increment in loop */
254	}
255#endif
256    }
257  return ((char *)NULL);
258}
259#endif
260
261#if !defined (HAVE_STRCASECMP)
262/* Compare at most COUNT characters from string1 to string2.  Case
263   doesn't matter. */
264int
265_rl_strnicmp (string1, string2, count)
266     char *string1, *string2;
267     int count;
268{
269  register char ch1, ch2;
270
271  while (count)
272    {
273      ch1 = *string1++;
274      ch2 = *string2++;
275      if (_rl_to_upper(ch1) == _rl_to_upper(ch2))
276	count--;
277      else
278        break;
279    }
280  return (count);
281}
282
283/* strcmp (), but caseless. */
284int
285_rl_stricmp (string1, string2)
286     char *string1, *string2;
287{
288  register char ch1, ch2;
289
290  while (*string1 && *string2)
291    {
292      ch1 = *string1++;
293      ch2 = *string2++;
294      if (_rl_to_upper(ch1) != _rl_to_upper(ch2))
295	return (1);
296    }
297  return (*string1 - *string2);
298}
299#endif /* !HAVE_STRCASECMP */
300
301/* Stupid comparison routine for qsort () ing strings. */
302int
303_rl_qsort_string_compare (s1, s2)
304  char **s1, **s2;
305{
306#if defined (HAVE_STRCOLL)
307  return (strcoll (*s1, *s2));
308#else
309  int result;
310
311  result = **s1 - **s2;
312  if (result == 0)
313    result = strcmp (*s1, *s2);
314
315  return result;
316#endif
317}
318
319/* Function equivalents for the macros defined in chardefs.h. */
320#define FUNCTION_FOR_MACRO(f)	int (f) (c) int c; { return f (c); }
321
322FUNCTION_FOR_MACRO (_rl_digit_p)
323FUNCTION_FOR_MACRO (_rl_digit_value)
324FUNCTION_FOR_MACRO (_rl_lowercase_p)
325FUNCTION_FOR_MACRO (_rl_pure_alphabetic)
326FUNCTION_FOR_MACRO (_rl_to_lower)
327FUNCTION_FOR_MACRO (_rl_to_upper)
328FUNCTION_FOR_MACRO (_rl_uppercase_p)
329
330/* Backwards compatibility, now that savestring has been removed from
331   all `public' readline header files. */
332#undef _rl_savestring
333char *
334_rl_savestring (s)
335     const char *s;
336{
337  return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s)));
338}
339