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