1/* bracecomp.c -- Complete a filename with the possible completions enclosed 2 in csh-style braces such that the list of completions is available to the 3 shell. */ 4 5/* Original version by tromey@cns.caltech.edu, Fri Feb 7 1992. */ 6 7/* Copyright (C) 1993 Free Software Foundation, Inc. 8 9 This file is part of GNU Bash, the Bourne Again SHell. 10 11 Bash is free software; you can redistribute it and/or modify it under 12 the terms of the GNU General Public License as published by the Free 13 Software Foundation; either version 2, or (at your option) any later 14 version. 15 16 Bash is distributed in the hope that it will be useful, but WITHOUT ANY 17 WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19 for more details. 20 21 You should have received a copy of the GNU General Public License along 22 with Bash; see the file COPYING. If not, write to the Free Software 23 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 24 25#include "config.h" 26#if defined (BRACE_EXPANSION) && defined (READLINE) 27 28#include <stdio.h> 29 30#if defined (HAVE_UNISTD_H) 31# ifdef _MINIX 32# include <sys/types.h> 33# endif 34# include <unistd.h> 35#endif 36 37#include "bashansi.h" 38 39#include "shell.h" 40#include <readline/readline.h> 41 42/* Find greatest common prefix of two strings. */ 43static int 44string_gcd (s1, s2) 45 char *s1, *s2; 46{ 47 register int i; 48 49 if (s1 == NULL || s2 == NULL) 50 return (0); 51 52 for (i = 0; *s1 && *s2; ++s1, ++s2, ++i) 53 { 54 if (*s1 != *s2) 55 break; 56 } 57 58 return (i); 59} 60 61static char * 62really_munge_braces (array, real_start, real_end, gcd_zero) 63 char **array; 64 int real_start, real_end, gcd_zero; 65{ 66 int start, end, gcd; 67 char *result, *subterm, *x; 68 int result_size, flag, tlen; 69 70 flag = 0; 71 72 if (real_start == real_end) 73 { 74 x = array[real_start] ? sh_backslash_quote (array[real_start] + gcd_zero) 75 : sh_backslash_quote (array[0]); 76 return x; 77 } 78 79 result = (char *)xmalloc (result_size = 16); 80 *result = '\0'; 81 82 for (start = real_start; start < real_end; start = end + 1) 83 { 84 gcd = strlen (array[start]); 85 for (end = start + 1; end < real_end; end++) 86 { 87 int temp; 88 89 temp = string_gcd (array[start], array[end]); 90 91 if (temp <= gcd_zero) 92 break; 93 94 gcd = temp; 95 } 96 end--; 97 98 if (gcd_zero == 0 && start == real_start && end != (real_end - 1)) 99 { 100 /* In this case, add in a leading '{', because we are at 101 top level, and there isn't a consistent prefix. */ 102 result_size += 1; 103 result = (char *)xrealloc (result, result_size); 104 result[0] = '{'; result[1] = '\0'; 105 flag++; 106 } 107 108 /* Make sure we backslash quote every substring we insert into the 109 resultant brace expression. This is so the default filename 110 quoting function won't inappropriately quote the braces. */ 111 if (start == end) 112 { 113 x = savestring (array[start] + gcd_zero); 114 subterm = sh_backslash_quote (x); 115 free (x); 116 } 117 else 118 { 119 /* If there is more than one element in the subarray, 120 insert the (quoted) prefix and an opening brace. */ 121 tlen = gcd - gcd_zero; 122 x = (char *)xmalloc (tlen + 1); 123 strncpy (x, array[start] + gcd_zero, tlen); 124 x[tlen] = '\0'; 125 subterm = sh_backslash_quote (x); 126 free (x); 127 result_size += strlen (subterm) + 1; 128 result = (char *)xrealloc (result, result_size); 129 strcat (result, subterm); 130 free (subterm); 131 strcat (result, "{"); 132 subterm = really_munge_braces (array, start, end + 1, gcd); 133 subterm[strlen (subterm) - 1] = '}'; 134 } 135 136 result_size += strlen (subterm) + 1; 137 result = (char *)xrealloc (result, result_size); 138 strcat (result, subterm); 139 strcat (result, ","); 140 free (subterm); 141 } 142 143 if (gcd_zero == 0) 144 result[strlen (result) - 1] = flag ? '}' : '\0'; 145 return (result); 146} 147 148static int 149hack_braces_completion (names) 150 char **names; 151{ 152 register int i; 153 char *temp; 154 155 temp = really_munge_braces (names, 1, strvec_len (names), 0); 156 157 for (i = 0; names[i]; ++i) 158 { 159 free (names[i]); 160 names[i] = NULL; 161 } 162 names[0] = temp; 163 return 0; 164} 165 166/* We handle quoting ourselves within hack_braces_completion, so we turn off 167 rl_filename_quoting_desired and rl_filename_quoting_function. */ 168int 169bash_brace_completion (count, ignore) 170 int count, ignore; 171{ 172 rl_compignore_func_t *orig_ignore_func; 173 rl_compentry_func_t *orig_entry_func; 174 rl_quote_func_t *orig_quoting_func; 175 rl_completion_func_t *orig_attempt_func; 176 int orig_quoting_desired, r; 177 178 orig_ignore_func = rl_ignore_some_completions_function; 179 orig_attempt_func = rl_attempted_completion_function; 180 orig_entry_func = rl_completion_entry_function; 181 orig_quoting_func = rl_filename_quoting_function; 182 orig_quoting_desired = rl_filename_quoting_desired; 183 184 rl_completion_entry_function = rl_filename_completion_function; 185 rl_attempted_completion_function = (rl_completion_func_t *)NULL; 186 rl_ignore_some_completions_function = hack_braces_completion; 187 rl_filename_quoting_function = (rl_quote_func_t *)NULL; 188 rl_filename_quoting_desired = 0; 189 190 r = rl_complete_internal (TAB); 191 192 rl_ignore_some_completions_function = orig_ignore_func; 193 rl_attempted_completion_function = orig_attempt_func; 194 rl_completion_entry_function = orig_entry_func; 195 rl_filename_quoting_function = orig_quoting_func; 196 rl_filename_quoting_desired = orig_quoting_desired; 197 198 return r; 199} 200#endif /* BRACE_EXPANSION && READLINE */ 201