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