]> git.ipfire.org Git - thirdparty/bash.git/blob - stringlib.c
Imported from ../bash-2.05a.tar.gz.
[thirdparty/bash.git] / stringlib.c
1 /* stringlib.c - Miscellaneous string functions. */
2
3 /* Copyright (C) 1996
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21
22 #include "config.h"
23
24 #include "bashtypes.h"
25
26 #if defined (HAVE_UNISTD_H)
27 # include <unistd.h>
28 #endif
29
30 #include "bashansi.h"
31 #include <stdio.h>
32 #include "chartypes.h"
33
34 #include "shell.h"
35 #include "pathexp.h"
36
37 #include <glob/glob.h>
38
39 #if defined (EXTENDED_GLOB)
40 # include <glob/strmatch.h>
41 #endif
42
43 /* **************************************************************** */
44 /* */
45 /* Functions to manage arrays of strings */
46 /* */
47 /* **************************************************************** */
48
49 /* Cons up a new array of words. The words are taken from LIST,
50 which is a WORD_LIST *. If COPY is true, everything is malloc'ed,
51 so you should free everything in this array when you are done.
52 The array is NULL terminated. If IP is non-null, it gets the
53 number of words in the returned array. STARTING_INDEX says where
54 to start filling in the returned array; it can be used to reserve
55 space at the beginning of the array. */
56 char **
57 word_list_to_argv (list, copy, starting_index, ip)
58 WORD_LIST *list;
59 int copy, starting_index, *ip;
60 {
61 int count;
62 char **array;
63
64 count = list_length (list);
65 array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
66
67 for (count = 0; count < starting_index; count++)
68 array[count] = (char *)NULL;
69 for (count = starting_index; list; count++, list = list->next)
70 array[count] = copy ? savestring (list->word->word) : list->word->word;
71 array[count] = (char *)NULL;
72
73 if (ip)
74 *ip = count;
75 return (array);
76 }
77
78 /* Convert an array of strings into the form used internally by the shell.
79 COPY means to copy the values in ARRAY into the returned list rather
80 than allocate new storage. STARTING_INDEX says where in ARRAY to begin. */
81 WORD_LIST *
82 argv_to_word_list (array, copy, starting_index)
83 char **array;
84 int copy, starting_index;
85 {
86 WORD_LIST *list;
87 WORD_DESC *w;
88 int i, count;
89
90 if (array == 0 || array[0] == 0)
91 return (WORD_LIST *)NULL;
92
93 for (count = 0; array[count]; count++)
94 ;
95
96 for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
97 {
98 w = make_bare_word (copy ? "" : array[i]);
99 if (copy)
100 {
101 free (w->word);
102 w->word = array[i];
103 }
104 list = make_word_list (w, list);
105 }
106 return (REVERSE_LIST(list, WORD_LIST *));
107 }
108
109 /* Find STRING in ALIST, a list of string key/int value pairs. If FLAGS
110 is 1, STRING is treated as a pattern and matched using strmatch. */
111 int
112 find_string_in_alist (string, alist, flags)
113 char *string;
114 STRING_INT_ALIST *alist;
115 int flags;
116 {
117 register int i;
118 int r;
119
120 for (i = r = 0; alist[i].word; i++)
121 {
122 #if defined (EXTENDED_GLOB)
123 if (flags)
124 r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
125 else
126 #endif
127 r = STREQ (string, alist[i].word);
128
129 if (r)
130 return (alist[i].token);
131 }
132 return -1;
133 }
134
135 /* **************************************************************** */
136 /* */
137 /* String Management Functions */
138 /* */
139 /* **************************************************************** */
140
141 /* Replace occurrences of PAT with REP in STRING. If GLOBAL is non-zero,
142 replace all occurrences, otherwise replace only the first.
143 This returns a new string; the caller should free it. */
144 char *
145 strsub (string, pat, rep, global)
146 char *string, *pat, *rep;
147 int global;
148 {
149 int patlen, replen, templen, tempsize, repl, i;
150 char *temp, *r;
151
152 patlen = strlen (pat);
153 replen = strlen (rep);
154 for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
155 {
156 if (repl && STREQN (string + i, pat, patlen))
157 {
158 if (replen)
159 RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2));
160
161 for (r = rep; *r; )
162 temp[templen++] = *r++;
163
164 i += patlen ? patlen : 1; /* avoid infinite recursion */
165 repl = global != 0;
166 }
167 else
168 {
169 RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 16);
170 temp[templen++] = string[i++];
171 }
172 }
173 temp[templen] = 0;
174 return (temp);
175 }
176
177 /* Replace all instances of C in STRING with TEXT. TEXT may be empty or
178 NULL. If DO_GLOB is non-zero, we quote the replacement text for
179 globbing. Backslash may be used to quote C. */
180 char *
181 strcreplace (string, c, text, do_glob)
182 char *string;
183 int c;
184 char *text;
185 int do_glob;
186 {
187 char *ret, *p, *r, *t;
188 int len, rlen, ind, tlen;
189
190 len = STRLEN (text);
191 rlen = len + strlen (string) + 2;
192 ret = (char *)xmalloc (rlen);
193
194 for (p = string, r = ret; p && *p; )
195 {
196 if (*p == c)
197 {
198 if (len)
199 {
200 ind = r - ret;
201 if (do_glob && (glob_pattern_p (text) || strchr (text, '\\')))
202 {
203 t = quote_globbing_chars (text);
204 tlen = strlen (t);
205 RESIZE_MALLOCED_BUFFER (ret, ind, tlen, rlen, rlen);
206 r = ret + ind; /* in case reallocated */
207 strcpy (r, t);
208 r += tlen;
209 free (t);
210 }
211 else
212 {
213 RESIZE_MALLOCED_BUFFER (ret, ind, len, rlen, rlen);
214 r = ret + ind; /* in case reallocated */
215 strcpy (r, text);
216 r += len;
217 }
218 }
219 p++;
220 continue;
221 }
222
223 if (*p == '\\' && p[1] == c)
224 p++;
225
226 ind = r - ret;
227 RESIZE_MALLOCED_BUFFER (ret, ind, 2, rlen, rlen);
228 r = ret + ind; /* in case reallocated */
229 *r++ = *p++;
230 }
231 *r = '\0';
232
233 return ret;
234 }
235
236 #ifdef INCLUDE_UNUSED
237 /* Remove all leading whitespace from STRING. This includes
238 newlines. STRING should be terminated with a zero. */
239 void
240 strip_leading (string)
241 char *string;
242 {
243 char *start = string;
244
245 while (*string && (whitespace (*string) || *string == '\n'))
246 string++;
247
248 if (string != start)
249 {
250 int len = strlen (string);
251 FASTCOPY (string, start, len);
252 start[len] = '\0';
253 }
254 }
255 #endif
256
257 /* Remove all trailing whitespace from STRING. This includes
258 newlines. If NEWLINES_ONLY is non-zero, only trailing newlines
259 are removed. STRING should be terminated with a zero. */
260 void
261 strip_trailing (string, len, newlines_only)
262 char *string;
263 int len;
264 int newlines_only;
265 {
266 while (len >= 0)
267 {
268 if ((newlines_only && string[len] == '\n') ||
269 (!newlines_only && whitespace (string[len])))
270 len--;
271 else
272 break;
273 }
274 string[len + 1] = '\0';
275 }
276
277 /* A wrapper for bcopy that can be prototyped in general.h */
278 void
279 xbcopy (s, d, n)
280 char *s, *d;
281 int n;
282 {
283 FASTCOPY (s, d, n);
284 }