Line data Source code
1 : /* pcomplib.c - library functions for programmable completion. */ 2 : 3 : /* Copyright (C) 1999-2009 Free Software Foundation, Inc. 4 : 5 : This file is part of GNU Bash, the Bourne Again SHell. 6 : 7 : Bash is free software: you can redistribute it and/or modify 8 : it under the terms of the GNU General Public License as published by 9 : the Free Software Foundation, either version 3 of the License, or 10 : (at your option) any later version. 11 : 12 : Bash is distributed in the hope that it will be useful, 13 : but WITHOUT ANY WARRANTY; without even the implied warranty of 14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 : GNU General Public License for more details. 16 : 17 : You should have received a copy of the GNU General Public License 18 : along with Bash. If not, see <http://www.gnu.org/licenses/>. 19 : */ 20 : 21 : #include <config.h> 22 : 23 : #if defined (PROGRAMMABLE_COMPLETION) 24 : 25 : #include "bashansi.h" 26 : #include <stdio.h> 27 : 28 : #if defined (HAVE_UNISTD_H) 29 : # ifdef _MINIX 30 : # include <sys/types.h> 31 : # endif 32 : # include <unistd.h> 33 : #endif 34 : 35 : #include "bashintl.h" 36 : 37 : #include "shell.h" 38 : #include "pcomplete.h" 39 : 40 : #define COMPLETE_HASH_BUCKETS 256 /* must be power of two */ 41 : 42 : #define STRDUP(x) ((x) ? savestring (x) : (char *)NULL) 43 : 44 : HASH_TABLE *prog_completes = (HASH_TABLE *)NULL; 45 : 46 : static void free_progcomp __P((PTR_T)); 47 : 48 : COMPSPEC * 49 34 : compspec_create () 50 : { 51 34 : COMPSPEC *ret; 52 : 53 34 : ret = (COMPSPEC *)xmalloc (sizeof (COMPSPEC)); 54 34 : ret->refcount = 0; 55 : 56 34 : ret->actions = (unsigned long)0; 57 34 : ret->options = (unsigned long)0; 58 : 59 34 : ret->globpat = (char *)NULL; 60 34 : ret->words = (char *)NULL; 61 34 : ret->prefix = (char *)NULL; 62 34 : ret->suffix = (char *)NULL; 63 34 : ret->funcname = (char *)NULL; 64 34 : ret->command = (char *)NULL; 65 34 : ret->lcommand = (char *)NULL; 66 34 : ret->filterpat = (char *)NULL; 67 : 68 34 : return ret; 69 : } 70 : 71 : void 72 0 : compspec_dispose (cs) 73 : COMPSPEC *cs; 74 : { 75 0 : cs->refcount--; 76 0 : if (cs->refcount == 0) 77 : { 78 0 : FREE (cs->globpat); 79 0 : FREE (cs->words); 80 0 : FREE (cs->prefix); 81 0 : FREE (cs->suffix); 82 0 : FREE (cs->funcname); 83 0 : FREE (cs->command); 84 0 : FREE (cs->lcommand); 85 0 : FREE (cs->filterpat); 86 : 87 0 : free (cs); 88 : } 89 0 : } 90 : 91 : COMPSPEC * 92 0 : compspec_copy (cs) 93 : COMPSPEC *cs; 94 : { 95 0 : COMPSPEC *new; 96 : 97 0 : new = (COMPSPEC *)xmalloc (sizeof (COMPSPEC)); 98 : 99 0 : new->refcount = 1; /* was cs->refcount, but this is a fresh copy */ 100 0 : new->actions = cs->actions; 101 0 : new->options = cs->options; 102 : 103 0 : new->globpat = STRDUP (cs->globpat); 104 0 : new->words = STRDUP (cs->words); 105 0 : new->prefix = STRDUP (cs->prefix); 106 0 : new->suffix = STRDUP (cs->suffix); 107 0 : new->funcname = STRDUP (cs->funcname); 108 0 : new->command = STRDUP (cs->command); 109 0 : new->lcommand = STRDUP (cs->lcommand); 110 0 : new->filterpat = STRDUP (cs->filterpat); 111 : 112 0 : return new; 113 : } 114 : 115 : void 116 0 : progcomp_create () 117 : { 118 0 : if (prog_completes == 0) 119 34 : prog_completes = hash_create (COMPLETE_HASH_BUCKETS); 120 0 : } 121 : 122 : int 123 0 : progcomp_size () 124 : { 125 0 : return (HASH_ENTRIES (prog_completes)); 126 : } 127 : 128 : static void 129 0 : free_progcomp (data) 130 : PTR_T data; 131 : { 132 0 : COMPSPEC *cs; 133 : 134 0 : cs = (COMPSPEC *)data; 135 0 : compspec_dispose (cs); 136 0 : } 137 : 138 : void 139 0 : progcomp_flush () 140 : { 141 0 : if (prog_completes) 142 0 : hash_flush (prog_completes, free_progcomp); 143 0 : } 144 : 145 : void 146 0 : progcomp_dispose () 147 : { 148 0 : if (prog_completes) 149 0 : hash_dispose (prog_completes); 150 0 : prog_completes = (HASH_TABLE *)NULL; 151 0 : } 152 : 153 : int 154 0 : progcomp_remove (cmd) 155 : char *cmd; 156 : { 157 0 : register BUCKET_CONTENTS *item; 158 : 159 0 : if (prog_completes == 0) 160 : return 1; 161 : 162 0 : item = hash_remove (cmd, prog_completes, 0); 163 0 : if (item) 164 : { 165 0 : if (item->data) 166 0 : free_progcomp (item->data); 167 0 : free (item->key); 168 0 : free (item); 169 0 : return (1); 170 : } 171 : return (0); 172 : } 173 : 174 : int 175 83 : progcomp_insert (cmd, cs) 176 : char *cmd; 177 : COMPSPEC *cs; 178 : { 179 83 : register BUCKET_CONTENTS *item; 180 : 181 83 : if (cs == NULL) 182 0 : programming_error (_("progcomp_insert: %s: NULL COMPSPEC"), cmd); 183 : 184 83 : if (prog_completes == 0) 185 34 : progcomp_create (); 186 : 187 83 : cs->refcount++; 188 83 : item = hash_insert (cmd, prog_completes, 0); 189 83 : if (item->data) 190 0 : free_progcomp (item->data); 191 : else 192 83 : item->key = savestring (cmd); 193 83 : item->data = cs; 194 : 195 83 : return 1; 196 : } 197 : 198 : COMPSPEC * 199 0 : progcomp_search (cmd) 200 : const char *cmd; 201 : { 202 0 : register BUCKET_CONTENTS *item; 203 0 : COMPSPEC *cs; 204 : 205 0 : if (prog_completes == 0) 206 : return ((COMPSPEC *)NULL); 207 : 208 0 : item = hash_search (cmd, prog_completes, 0); 209 : 210 0 : if (item == NULL) 211 : return ((COMPSPEC *)NULL); 212 : 213 0 : cs = (COMPSPEC *)item->data; 214 : 215 0 : return (cs); 216 : } 217 : 218 : void 219 50 : progcomp_walk (pfunc) 220 : hash_wfunc *pfunc; 221 : { 222 50 : if (prog_completes == 0 || pfunc == 0 || HASH_ENTRIES (prog_completes) == 0) 223 : return; 224 : 225 0 : hash_walk (prog_completes, pfunc); 226 : } 227 : 228 : #endif /* PROGRAMMABLE_COMPLETION */