[PATCH 47/57][Arm][OBJDUMP] Add support for MVE instructions: vaddv, vmlaldav, vmlada...
[binutils-gdb.git] / readline / tilde.c
blobd4c1da9e68d0a599e176ab8eabf8bac40ac4ffc9
1 /* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
3 /* Copyright (C) 1988-2009 Free Software Foundation, Inc.
5 This file is part of the GNU Readline Library (Readline), a library
6 for reading lines of text with interactive input and history editing.
8 Readline is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 Readline is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Readline. If not, see <http://www.gnu.org/licenses/>.
22 #if defined (HAVE_CONFIG_H)
23 # include <config.h>
24 #endif
26 #if defined (HAVE_UNISTD_H)
27 # ifdef _MINIX
28 # include <sys/types.h>
29 # endif
30 # include <unistd.h>
31 #endif
33 #if defined (HAVE_STRING_H)
34 # include <string.h>
35 #else /* !HAVE_STRING_H */
36 # include <strings.h>
37 #endif /* !HAVE_STRING_H */
39 #if defined (HAVE_STDLIB_H)
40 # include <stdlib.h>
41 #else
42 # include "ansi_stdlib.h"
43 #endif /* HAVE_STDLIB_H */
45 #include <sys/types.h>
46 #if defined (HAVE_PWD_H)
47 #include <pwd.h>
48 #endif
50 #include "tilde.h"
52 #if defined (TEST) || defined (STATIC_MALLOC)
53 static void *xmalloc (), *xrealloc ();
54 #else
55 # include "xmalloc.h"
56 #endif /* TEST || STATIC_MALLOC */
58 #if !defined (HAVE_GETPW_DECLS)
59 # if defined (HAVE_GETPWUID)
60 extern struct passwd *getpwuid PARAMS((uid_t));
61 # endif
62 # if defined (HAVE_GETPWNAM)
63 extern struct passwd *getpwnam PARAMS((const char *));
64 # endif
65 #endif /* !HAVE_GETPW_DECLS */
67 #if !defined (savestring)
68 #define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x))
69 #endif /* !savestring */
71 #if !defined (NULL)
72 # if defined (__STDC__)
73 # define NULL ((void *) 0)
74 # else
75 # define NULL 0x0
76 # endif /* !__STDC__ */
77 #endif /* !NULL */
79 /* If being compiled as part of bash, these will be satisfied from
80 variables.o. If being compiled as part of readline, they will
81 be satisfied from shell.o. */
82 extern char *sh_get_home_dir PARAMS((void));
83 extern char *sh_get_env_value PARAMS((const char *));
85 /* The default value of tilde_additional_prefixes. This is set to
86 whitespace preceding a tilde so that simple programs which do not
87 perform any word separation get desired behaviour. */
88 static const char *default_prefixes[] =
89 { " ~", "\t~", (const char *)NULL };
91 /* The default value of tilde_additional_suffixes. This is set to
92 whitespace or newline so that simple programs which do not
93 perform any word separation get desired behaviour. */
94 static const char *default_suffixes[] =
95 { " ", "\n", (const char *)NULL };
97 /* If non-null, this contains the address of a function that the application
98 wants called before trying the standard tilde expansions. The function
99 is called with the text sans tilde, and returns a malloc()'ed string
100 which is the expansion, or a NULL pointer if the expansion fails. */
101 tilde_hook_func_t *tilde_expansion_preexpansion_hook = (tilde_hook_func_t *)NULL;
103 /* If non-null, this contains the address of a function to call if the
104 standard meaning for expanding a tilde fails. The function is called
105 with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
106 which is the expansion, or a NULL pointer if there is no expansion. */
107 tilde_hook_func_t *tilde_expansion_failure_hook = (tilde_hook_func_t *)NULL;
109 /* When non-null, this is a NULL terminated array of strings which
110 are duplicates for a tilde prefix. Bash uses this to expand
111 `=~' and `:~'. */
112 char **tilde_additional_prefixes = (char **)default_prefixes;
114 /* When non-null, this is a NULL terminated array of strings which match
115 the end of a username, instead of just "/". Bash sets this to
116 `:' and `=~'. */
117 char **tilde_additional_suffixes = (char **)default_suffixes;
119 static int tilde_find_prefix PARAMS((const char *, int *));
120 static int tilde_find_suffix PARAMS((const char *));
121 static char *isolate_tilde_prefix PARAMS((const char *, int *));
122 static char *glue_prefix_and_suffix PARAMS((char *, const char *, int));
124 /* Find the start of a tilde expansion in STRING, and return the index of
125 the tilde which starts the expansion. Place the length of the text
126 which identified this tilde starter in LEN, excluding the tilde itself. */
127 static int
128 tilde_find_prefix (string, len)
129 const char *string;
130 int *len;
132 register int i, j, string_len;
133 register char **prefixes;
135 prefixes = tilde_additional_prefixes;
137 string_len = strlen (string);
138 *len = 0;
140 if (*string == '\0' || *string == '~')
141 return (0);
143 if (prefixes)
145 for (i = 0; i < string_len; i++)
147 for (j = 0; prefixes[j]; j++)
149 if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
151 *len = strlen (prefixes[j]) - 1;
152 return (i + *len);
157 return (string_len);
160 /* Find the end of a tilde expansion in STRING, and return the index of
161 the character which ends the tilde definition. */
162 static int
163 tilde_find_suffix (string)
164 const char *string;
166 register int i, j, string_len;
167 register char **suffixes;
169 suffixes = tilde_additional_suffixes;
170 string_len = strlen (string);
172 for (i = 0; i < string_len; i++)
174 #if defined (__MSDOS__)
175 if (string[i] == '/' || string[i] == '\\' /* || !string[i] */)
176 #else
177 if (string[i] == '/' /* || !string[i] */)
178 #endif
179 break;
181 for (j = 0; suffixes && suffixes[j]; j++)
183 if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
184 return (i);
187 return (i);
190 /* Return a new string which is the result of tilde expanding STRING. */
191 char *
192 tilde_expand (string)
193 const char *string;
195 char *result;
196 int result_size, result_index;
198 result_index = result_size = 0;
199 if (result = strchr (string, '~'))
200 result = (char *)xmalloc (result_size = (strlen (string) + 16));
201 else
202 result = (char *)xmalloc (result_size = (strlen (string) + 1));
204 /* Scan through STRING expanding tildes as we come to them. */
205 while (1)
207 register int start, end;
208 char *tilde_word, *expansion;
209 int len;
211 /* Make START point to the tilde which starts the expansion. */
212 start = tilde_find_prefix (string, &len);
214 /* Copy the skipped text into the result. */
215 if ((result_index + start + 1) > result_size)
216 result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
218 strncpy (result + result_index, string, start);
219 result_index += start;
221 /* Advance STRING to the starting tilde. */
222 string += start;
224 /* Make END be the index of one after the last character of the
225 username. */
226 end = tilde_find_suffix (string);
228 /* If both START and END are zero, we are all done. */
229 if (!start && !end)
230 break;
232 /* Expand the entire tilde word, and copy it into RESULT. */
233 tilde_word = (char *)xmalloc (1 + end);
234 strncpy (tilde_word, string, end);
235 tilde_word[end] = '\0';
236 string += end;
238 expansion = tilde_expand_word (tilde_word);
239 xfree (tilde_word);
241 len = strlen (expansion);
242 #ifdef __CYGWIN__
243 /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when
244 $HOME for `user' is /. On cygwin, // denotes a network drive. */
245 if (len > 1 || *expansion != '/' || *string != '/')
246 #endif
248 if ((result_index + len + 1) > result_size)
249 result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
251 strcpy (result + result_index, expansion);
252 result_index += len;
254 xfree (expansion);
257 result[result_index] = '\0';
259 return (result);
262 /* Take FNAME and return the tilde prefix we want expanded. If LENP is
263 non-null, the index of the end of the prefix into FNAME is returned in
264 the location it points to. */
265 static char *
266 isolate_tilde_prefix (fname, lenp)
267 const char *fname;
268 int *lenp;
270 char *ret;
271 int i;
273 ret = (char *)xmalloc (strlen (fname));
274 #if defined (__MSDOS__)
275 for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++)
276 #else
277 for (i = 1; fname[i] && fname[i] != '/'; i++)
278 #endif
279 ret[i - 1] = fname[i];
280 ret[i - 1] = '\0';
281 if (lenp)
282 *lenp = i;
283 return ret;
286 #if 0
287 /* Public function to scan a string (FNAME) beginning with a tilde and find
288 the portion of the string that should be passed to the tilde expansion
289 function. Right now, it just calls tilde_find_suffix and allocates new
290 memory, but it can be expanded to do different things later. */
291 char *
292 tilde_find_word (fname, flags, lenp)
293 const char *fname;
294 int flags, *lenp;
296 int x;
297 char *r;
299 x = tilde_find_suffix (fname);
300 if (x == 0)
302 r = savestring (fname);
303 if (lenp)
304 *lenp = 0;
306 else
308 r = (char *)xmalloc (1 + x);
309 strncpy (r, fname, x);
310 r[x] = '\0';
311 if (lenp)
312 *lenp = x;
315 return r;
317 #endif
319 /* Return a string that is PREFIX concatenated with SUFFIX starting at
320 SUFFIND. */
321 static char *
322 glue_prefix_and_suffix (prefix, suffix, suffind)
323 char *prefix;
324 const char *suffix;
325 int suffind;
327 char *ret;
328 int plen, slen;
330 plen = (prefix && *prefix) ? strlen (prefix) : 0;
331 slen = strlen (suffix + suffind);
332 ret = (char *)xmalloc (plen + slen + 1);
333 if (plen)
334 strcpy (ret, prefix);
335 strcpy (ret + plen, suffix + suffind);
336 return ret;
339 /* Do the work of tilde expansion on FILENAME. FILENAME starts with a
340 tilde. If there is no expansion, call tilde_expansion_failure_hook.
341 This always returns a newly-allocated string, never static storage. */
342 char *
343 tilde_expand_word (filename)
344 const char *filename;
346 char *dirname, *expansion, *username;
347 int user_len;
348 struct passwd *user_entry;
350 if (filename == 0)
351 return ((char *)NULL);
353 if (*filename != '~')
354 return (savestring (filename));
356 /* A leading `~/' or a bare `~' is *always* translated to the value of
357 $HOME or the home directory of the current user, regardless of any
358 preexpansion hook. */
359 if (filename[1] == '\0' || filename[1] == '/')
361 /* Prefix $HOME to the rest of the string. */
362 expansion = sh_get_env_value ("HOME");
363 #ifdef _WIN32
364 if (!expansion)
365 expansion = sh_get_env_value ("APPDATA");
366 #endif
368 /* If there is no HOME variable, look up the directory in
369 the password database. */
370 if (expansion == 0)
371 expansion = sh_get_home_dir ();
373 return (glue_prefix_and_suffix (expansion, filename, 1));
376 username = isolate_tilde_prefix (filename, &user_len);
378 if (tilde_expansion_preexpansion_hook)
380 expansion = (*tilde_expansion_preexpansion_hook) (username);
381 if (expansion)
383 dirname = glue_prefix_and_suffix (expansion, filename, user_len);
384 xfree (username);
385 xfree (expansion);
386 return (dirname);
390 /* No preexpansion hook, or the preexpansion hook failed. Look in the
391 password database. */
392 dirname = (char *)NULL;
393 #if defined (HAVE_GETPWNAM)
394 user_entry = getpwnam (username);
395 #else
396 user_entry = 0;
397 #endif
398 if (user_entry == 0)
400 /* If the calling program has a special syntax for expanding tildes,
401 and we couldn't find a standard expansion, then let them try. */
402 if (tilde_expansion_failure_hook)
404 expansion = (*tilde_expansion_failure_hook) (username);
405 if (expansion)
407 dirname = glue_prefix_and_suffix (expansion, filename, user_len);
408 xfree (expansion);
411 /* If we don't have a failure hook, or if the failure hook did not
412 expand the tilde, return a copy of what we were passed. */
413 if (dirname == 0)
414 dirname = savestring (filename);
416 #if defined (HAVE_GETPWENT)
417 else
418 dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len);
419 #endif
421 xfree (username);
422 #if defined (HAVE_GETPWENT)
423 endpwent ();
424 #endif
425 return (dirname);
429 #if defined (TEST)
430 #undef NULL
431 #include <stdio.h>
433 main (argc, argv)
434 int argc;
435 char **argv;
437 char *result, line[512];
438 int done = 0;
440 while (!done)
442 printf ("~expand: ");
443 fflush (stdout);
445 if (!gets (line))
446 strcpy (line, "done");
448 if ((strcmp (line, "done") == 0) ||
449 (strcmp (line, "quit") == 0) ||
450 (strcmp (line, "exit") == 0))
452 done = 1;
453 break;
456 result = tilde_expand (line);
457 printf (" --> %s\n", result);
458 free (result);
460 exit (0);
463 static void memory_error_and_abort ();
465 static void *
466 xmalloc (bytes)
467 size_t bytes;
469 void *temp = (char *)malloc (bytes);
471 if (!temp)
472 memory_error_and_abort ();
473 return (temp);
476 static void *
477 xrealloc (pointer, bytes)
478 void *pointer;
479 int bytes;
481 void *temp;
483 if (!pointer)
484 temp = malloc (bytes);
485 else
486 temp = realloc (pointer, bytes);
488 if (!temp)
489 memory_error_and_abort ();
491 return (temp);
494 static void
495 memory_error_and_abort ()
497 fprintf (stderr, "readline: out of virtual memory\n");
498 abort ();
502 * Local variables:
503 * compile-command: "gcc -g -DTEST -o tilde tilde.c"
504 * end:
506 #endif /* TEST */