efc6fa57f93a160542d2a025784c565baf013f57
[platform/upstream/bash.git] / lib / sh / stringlist.c
1 /* stringlist.c - functions to handle a generic `list of strings' structure */
2
3 /* Copyright (C) 2000-2002 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 (HAVE_UNISTD_H)
24 #  include <unistd.h>
25 #endif
26
27 #include <stdio.h>
28 #include <bashansi.h>
29
30 #include "shell.h"
31
32 #ifdef STRDUP
33 #  undef STRDUP
34 #endif
35 #define STRDUP(x)       ((x) ? savestring (x) : (char *)NULL)
36
37 /* Allocate a new STRINGLIST, with room for N strings. */
38
39 STRINGLIST *
40 strlist_create (n)
41      int n;
42 {
43   STRINGLIST *ret;
44   register int i;
45
46   ret = (STRINGLIST *)xmalloc (sizeof (STRINGLIST));
47   if (n)
48     {
49       ret->list = strvec_create (n+1);
50       ret->list_size = n;
51       for (i = 0; i < n; i++)
52         ret->list[i] = (char *)NULL;
53     }
54   else
55     {
56       ret->list = (char **)NULL;
57       ret->list_size = 0;
58     }
59   ret->list_len = 0;
60   return ret;
61 }
62
63 STRINGLIST *
64 strlist_resize (sl, n)
65      STRINGLIST *sl;
66      int n;
67 {
68   register int i;
69
70   if (sl == 0)
71     return (sl = strlist_create (n));
72
73   if (n > sl->list_size)
74     {
75       sl->list = strvec_resize (sl->list, n + 1);
76       for (i = sl->list_size; i <= n; i++)
77         sl->list[i] = (char *)NULL;
78       sl->list_size = n;
79     }
80   return sl;
81 }
82
83 void
84 strlist_flush (sl)
85      STRINGLIST *sl;
86 {
87   if (sl == 0 || sl->list == 0)
88     return;
89   strvec_flush (sl->list);
90   sl->list_len = 0;
91 }
92   
93 void
94 strlist_dispose (sl)
95      STRINGLIST *sl;
96 {
97   if (sl == 0)
98     return;
99   if (sl->list)
100     strvec_dispose (sl->list);
101   free (sl);
102 }
103
104 int
105 strlist_remove (sl, s)
106      STRINGLIST *sl;
107      char *s;
108 {
109   int r;
110
111   if (sl == 0 || sl->list == 0 || sl->list_len == 0)
112     return 0;
113
114   r = strvec_remove (sl->list, s);
115   if (r)
116     sl->list_len--;
117   return r;
118 }
119
120 STRINGLIST *
121 strlist_copy (sl)
122      STRINGLIST *sl;
123 {
124   STRINGLIST *new;
125   register int i;
126
127   if (sl == 0)
128     return ((STRINGLIST *)0);
129   new = strlist_create (sl->list_size);
130   /* I'd like to use strvec_copy, but that doesn't copy everything. */
131   if (sl->list)
132     {
133       for (i = 0; i < sl->list_size; i++)
134         new->list[i] = STRDUP (sl->list[i]);
135     }
136   new->list_size = sl->list_size;
137   new->list_len = sl->list_len;
138   /* just being careful */
139   if (new->list)
140     new->list[new->list_len] = (char *)NULL;
141   return new;
142 }
143
144 /* Return a new STRINGLIST with everything from M1 and M2. */
145
146 STRINGLIST *
147 strlist_merge (m1, m2)
148      STRINGLIST *m1, *m2;
149 {
150   STRINGLIST *sl;
151   int i, n, l1, l2;
152
153   l1 = m1 ? m1->list_len : 0;
154   l2 = m2 ? m2->list_len : 0;
155
156   sl = strlist_create (l1 + l2 + 1);
157   for (i = n = 0; i < l1; i++, n++)
158     sl->list[n] = STRDUP (m1->list[i]);
159   for (i = 0; i < l2; i++, n++)
160     sl->list[n] = STRDUP (m2->list[i]);
161   sl->list_len = n;
162   sl->list[n] = (char *)NULL;
163   return (sl);
164 }
165
166 /* Make STRINGLIST M1 contain everything in M1 and M2. */
167 STRINGLIST *
168 strlist_append (m1, m2)
169      STRINGLIST *m1, *m2;
170 {
171   register int i, n, len1, len2;
172
173   if (m1 == 0)
174     return (m2 ? strlist_copy (m2) : (STRINGLIST *)0);
175
176   len1 = m1->list_len;
177   len2 = m2 ? m2->list_len : 0;
178
179   if (len2)
180     {
181       m1 = strlist_resize (m1, len1 + len2 + 1);
182       for (i = 0, n = len1; i < len2; i++, n++)
183         m1->list[n] = STRDUP (m2->list[i]);
184       m1->list[n] = (char *)NULL;
185       m1->list_len = n;
186     }
187
188   return m1;
189 }
190
191 STRINGLIST *
192 strlist_prefix_suffix (sl, prefix, suffix)
193      STRINGLIST *sl;
194      char *prefix, *suffix;
195 {
196   int plen, slen, tlen, llen, i;
197   char *t;
198
199   if (sl == 0 || sl->list == 0 || sl->list_len == 0)
200     return sl;
201
202   plen = STRLEN (prefix);
203   slen = STRLEN (suffix);
204
205   if (plen == 0 && slen == 0)
206     return (sl);
207
208   for (i = 0; i < sl->list_len; i++)
209     {
210       llen = STRLEN (sl->list[i]);
211       tlen = plen + llen + slen + 1;
212       t = (char *)xmalloc (tlen + 1);
213       if (plen)
214         strcpy (t, prefix);
215       strcpy (t + plen, sl->list[i]);
216       if (slen)
217         strcpy (t + plen + llen, suffix);
218       free (sl->list[i]);
219       sl->list[i] = t;
220     }
221
222   return (sl);   
223 }
224    
225 void
226 strlist_print (sl, prefix)
227      STRINGLIST *sl;
228      char *prefix;
229 {
230   register int i;
231
232   if (sl == 0)
233     return;
234   for (i = 0; i < sl->list_len; i++)
235     printf ("%s%s\n", prefix ? prefix : "", sl->list[i]);
236 }
237
238 void
239 strlist_walk (sl, func)
240      STRINGLIST *sl;
241      sh_strlist_map_func_t *func;
242 {
243   register int i;
244
245   if (sl == 0)
246     return;
247   for (i = 0; i < sl->list_len; i++)
248     if ((*func)(sl->list[i]) < 0)
249       break;
250
251      
252 void
253 strlist_sort (sl)
254      STRINGLIST *sl;
255 {
256   if (sl == 0 || sl->list_len == 0 || sl->list == 0)
257     return;
258   strvec_sort (sl->list);
259 }
260
261 STRINGLIST *
262 strlist_from_word_list (list, alloc, starting_index, ip)
263      WORD_LIST *list;
264      int alloc, starting_index, *ip;
265 {
266   STRINGLIST *ret;
267   int slen, len;
268
269   if (list == 0)
270     {
271       if (ip)
272         *ip = 0;
273       return ((STRINGLIST *)0);
274     }
275   slen = list_length (list);
276   ret = (STRINGLIST *)xmalloc (sizeof (STRINGLIST));
277   ret->list = strvec_from_word_list (list, alloc, starting_index, &len);
278   ret->list_size = slen + starting_index;
279   ret->list_len = len;
280   if (ip)
281     *ip = len;
282   return ret;
283 }
284
285 WORD_LIST *
286 strlist_to_word_list (sl, alloc, starting_index)
287      STRINGLIST *sl;
288      int alloc, starting_index;
289 {
290   WORD_LIST *list;
291
292   if (sl == 0 || sl->list == 0)
293     return ((WORD_LIST *)NULL);
294
295   list = strvec_to_word_list (sl->list, alloc, starting_index);
296   return list;
297 }