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 
67 int _rl_allow_pathname_alphabetic_chars = 0;
68 static const char *pathname_alphabetic_chars = "/-_=~.#$";
69 
70 int
rl_alphabetic(c)71 rl_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. */
82 int
_rl_abort_internal()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 
99 int
rl_abort(count,key)100 rl_abort (count, key)
101      int count, key;
102 {
103   return (_rl_abort_internal ());
104 }
105 
106 int
rl_tty_status(count,key)107 rl_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. */
121 char *
rl_copy_text(from,to)122 rl_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. */
141 void
rl_extend_line_buffer(len)142 rl_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. */
156 int
rl_tilde_expand(ignore,key)157 rl_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. */
214 char *
_rl_strindex(s1,s2)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. */
229 char *
_rl_strpbrk(string1,string2)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. */
264 int
_rl_strnicmp(string1,string2,count)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. */
284 int
_rl_stricmp(string1,string2)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. */
302 int
_rl_qsort_string_compare(s1,s2)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 
322 FUNCTION_FOR_MACRO (_rl_digit_p)
323 FUNCTION_FOR_MACRO (_rl_digit_value)
324 FUNCTION_FOR_MACRO (_rl_lowercase_p)
325 FUNCTION_FOR_MACRO (_rl_pure_alphabetic)
326 FUNCTION_FOR_MACRO (_rl_to_lower)
327 FUNCTION_FOR_MACRO (_rl_to_upper)
328 FUNCTION_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
333 char *
334 _rl_savestring (s)
335      const char *s;
336 {
337   return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s)));
338 }
339