845f6ac1263097de977138b8151af62c941a6b9f
[platform/upstream/bash.git] / pcomplib.c
1 /* pcomplib.c - library functions for programmable completion. */
2
3 /* Copyright (C) 1999 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 it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 2, or (at your option) any later
10    version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16
17    You should have received a copy of the GNU General Public License along
18    with Bash; see the file COPYING.  If not, write to the Free Software
19    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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 "shell.h"
36 #include "pcomplete.h"
37
38 #define COMPLETE_HASH_BUCKETS   29      /* for testing */
39
40 #define STRDUP(x)       ((x) ? savestring (x) : (char *)NULL)
41
42 HASH_TABLE *prog_completes = (HASH_TABLE *)NULL;
43
44 static void free_progcomp __P((PTR_T));
45
46 static int progcomp_initialized = 0;
47
48 COMPSPEC *
49 alloc_compspec ()
50 {
51   COMPSPEC *ret;
52
53   ret = (COMPSPEC *)xmalloc (sizeof (COMPSPEC));
54   ret->refcount = 0;
55
56   ret->actions = (unsigned long)0;
57   ret->options = (unsigned long)0;
58
59   ret->globpat = (char *)NULL;
60   ret->words = (char *)NULL;
61   ret->prefix = (char *)NULL;
62   ret->suffix = (char *)NULL;
63   ret->funcname = (char *)NULL;
64   ret->command = (char *)NULL;
65   ret->filterpat = (char *)NULL;
66
67   return ret;
68 }
69
70 void
71 free_compspec (cs)
72      COMPSPEC *cs;
73 {
74   cs->refcount--;
75   if (cs->refcount == 0)
76     {
77       FREE (cs->globpat);
78       FREE (cs->words);
79       FREE (cs->prefix);
80       FREE (cs->suffix);
81       FREE (cs->funcname);
82       FREE (cs->command);
83       FREE (cs->filterpat);
84
85       free (cs);
86     }
87 }
88
89 COMPSPEC *
90 copy_compspec (cs)
91      COMPSPEC *cs;
92 {
93   COMPSPEC *new;
94
95   new = (COMPSPEC *)xmalloc (sizeof (COMPSPEC));
96
97   new->refcount = cs->refcount;
98   new->actions = cs->actions;
99   new->options = cs->options;
100
101   new->globpat = STRDUP (cs->globpat);
102   new->words = STRDUP (cs->words);
103   new->prefix = STRDUP (cs->prefix);
104   new->suffix = STRDUP (cs->suffix);
105   new->funcname = STRDUP (cs->funcname);
106   new->command = STRDUP (cs->command);
107   new->filterpat = STRDUP (cs->filterpat);
108
109   return new;
110 }
111
112 void
113 initialize_progcomp ()
114 {
115   if (progcomp_initialized == 0)
116     {
117       prog_completes = make_hash_table (COMPLETE_HASH_BUCKETS);
118       progcomp_initialized = 1;
119     }
120 }
121
122 int
123 num_progcomps ()
124 {
125   if (progcomp_initialized == 0 || prog_completes == 0)
126     return (0);
127   return (prog_completes->nentries);
128 }
129
130 static void
131 free_progcomp (data)
132      PTR_T data;
133 {
134   COMPSPEC *cs;
135
136   cs = (COMPSPEC *)data;
137   free_compspec (cs);
138 }
139   
140 void
141 clear_progcomps ()
142 {
143   if (prog_completes)
144     flush_hash_table (prog_completes, free_progcomp);
145 }
146
147 int
148 remove_progcomp (cmd)
149      char *cmd;
150 {
151   register BUCKET_CONTENTS *item;
152
153   if (prog_completes == 0)
154     return 1;
155
156   item = remove_hash_item (cmd, prog_completes);
157   if (item)
158     {
159       free_progcomp (item->data);
160       free (item->key);
161       free (item);
162       return (1);
163     }
164   return (0);
165 }
166
167 int
168 add_progcomp (cmd, cs)
169       char *cmd;
170       COMPSPEC *cs;
171 {
172   register BUCKET_CONTENTS *item;
173
174   if (progcomp_initialized == 0 || prog_completes == 0)
175     initialize_progcomp ();
176
177   if (cs == NULL)
178     programming_error ("add_progcomp: %s: NULL COMPSPEC", cmd);
179
180   item = add_hash_item (cmd, prog_completes);
181   if (item->data)
182     free_progcomp (item->data);
183   else
184     item->key = savestring (cmd);
185   item->data = (char *)cs;
186   cs->refcount++;
187   return 1;
188 }
189
190 COMPSPEC *
191 find_compspec (cmd)
192      const char *cmd;
193 {
194   register BUCKET_CONTENTS *item;
195   COMPSPEC *cs;
196
197   if (prog_completes == 0)
198     return ((COMPSPEC *)NULL);
199
200   item = find_hash_item (cmd, prog_completes);
201
202   if (item == NULL)
203     return ((COMPSPEC *)NULL);
204
205   cs = (COMPSPEC *)item->data;
206
207   return (cs);
208 }
209
210 void
211 print_all_compspecs (pfunc)
212      sh_csprint_func_t *pfunc;
213 {
214   BUCKET_CONTENTS *item_list;
215   int bucket;
216   COMPSPEC *cs;
217
218   if (prog_completes == 0 || pfunc == 0)
219     return;
220
221   for (bucket = 0; bucket < prog_completes->nbuckets; bucket++)
222     {
223       item_list = get_hash_bucket (bucket, prog_completes);
224       if (item_list == 0)
225         continue;
226
227       for ( ; item_list; item_list = item_list->next)
228         {
229           cs = (COMPSPEC *)item_list->data;
230           (*pfunc) (item_list->key, cs);
231         }
232     }
233 }
234
235 #endif /* PROGRAMMABLE_COMPLETION */