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