xref: /NextBSD/contrib/libreadline/util.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
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 
69 int _rl_allow_pathname_alphabetic_chars = 0;
70 static const char *pathname_alphabetic_chars = "/-_=~.#$";
71 
72 int
rl_alphabetic(c)73 rl_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)
84 int
_rl_walphabetic(wc)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. */
100 int
_rl_abort_internal()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 
117 int
rl_abort(count,key)118 rl_abort (count, key)
119      int count, key;
120 {
121   return (_rl_abort_internal ());
122 }
123 
124 int
rl_tty_status(count,key)125 rl_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. */
139 char *
rl_copy_text(from,to)140 rl_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. */
159 void
rl_extend_line_buffer(len)160 rl_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. */
174 int
rl_tilde_expand(ignore,key)175 rl_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. */
232 char *
_rl_strindex(s1,s2)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. */
247 char *
_rl_strpbrk(string1,string2)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. */
282 int
_rl_strnicmp(string1,string2,count)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. */
302 int
_rl_stricmp(string1,string2)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. */
320 int
_rl_qsort_string_compare(s1,s2)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 
340 FUNCTION_FOR_MACRO (_rl_digit_p)
341 FUNCTION_FOR_MACRO (_rl_digit_value)
342 FUNCTION_FOR_MACRO (_rl_lowercase_p)
343 FUNCTION_FOR_MACRO (_rl_pure_alphabetic)
344 FUNCTION_FOR_MACRO (_rl_to_lower)
345 FUNCTION_FOR_MACRO (_rl_to_upper)
346 FUNCTION_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
351 char *
352 _rl_savestring (s)
353      const char *s;
354 {
355   return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s)));
356 }
357