Line data Source code
1 : /* stringlib.c - Miscellaneous string functions. */
2 :
3 : /* Copyright (C) 1996-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 : #include "bashtypes.h"
24 :
25 : #if defined (HAVE_UNISTD_H)
26 : # include <unistd.h>
27 : #endif
28 :
29 : #include "bashansi.h"
30 : #include <stdio.h>
31 : #include "chartypes.h"
32 :
33 : #include "shell.h"
34 : #include "pathexp.h"
35 :
36 : #include <glob/glob.h>
37 :
38 : #if defined (EXTENDED_GLOB)
39 : # include <glob/strmatch.h>
40 : #endif
41 :
42 : /* **************************************************************** */
43 : /* */
44 : /* Functions to manage arrays of strings */
45 : /* */
46 : /* **************************************************************** */
47 :
48 : /* Find STRING in ALIST, a list of string key/int value pairs. If FLAGS
49 : is 1, STRING is treated as a pattern and matched using strmatch. */
50 : int
51 154816 : find_string_in_alist (string, alist, flags)
52 : char *string;
53 : STRING_INT_ALIST *alist;
54 : int flags;
55 : {
56 154816 : register int i;
57 154816 : int r;
58 :
59 154816 : for (i = r = 0; alist[i].word; i++)
60 : {
61 : #if defined (EXTENDED_GLOB)
62 0 : if (flags)
63 0 : r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
64 : else
65 : #endif
66 0 : r = STREQ (string, alist[i].word);
67 :
68 0 : if (r)
69 0 : return (alist[i].token);
70 : }
71 : return -1;
72 : }
73 :
74 : /* Find TOKEN in ALIST, a list of string/int value pairs. Return the
75 : corresponding string. Allocates memory for the returned
76 : string. FLAGS is currently ignored, but reserved. */
77 : char *
78 3430178 : find_token_in_alist (token, alist, flags)
79 : int token;
80 : STRING_INT_ALIST *alist;
81 : int flags;
82 : {
83 3430178 : register int i;
84 :
85 78525080 : for (i = 0; alist[i].word; i++)
86 : {
87 76747236 : if (alist[i].token == token)
88 1652334 : return (savestring (alist[i].word));
89 : }
90 : return ((char *)NULL);
91 : }
92 :
93 : int
94 0 : find_index_in_alist (string, alist, flags)
95 : char *string;
96 : STRING_INT_ALIST *alist;
97 : int flags;
98 : {
99 0 : register int i;
100 0 : int r;
101 :
102 0 : for (i = r = 0; alist[i].word; i++)
103 : {
104 : #if defined (EXTENDED_GLOB)
105 0 : if (flags)
106 0 : r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
107 : else
108 : #endif
109 0 : r = STREQ (string, alist[i].word);
110 :
111 0 : if (r)
112 0 : return (i);
113 : }
114 :
115 : return -1;
116 : }
117 :
118 : /* **************************************************************** */
119 : /* */
120 : /* String Management Functions */
121 : /* */
122 : /* **************************************************************** */
123 :
124 : /* Cons a new string from STRING starting at START and ending at END,
125 : not including END. */
126 : char *
127 89392649 : substring (string, start, end)
128 : const char *string;
129 : int start, end;
130 : {
131 89392649 : register int len;
132 89392649 : register char *result;
133 :
134 89392649 : len = end - start;
135 89392649 : result = (char *)xmalloc (len + 1);
136 178785298 : memcpy (result, string + start, len);
137 89392649 : result[len] = '\0';
138 89392649 : return (result);
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 0 : strsub (string, pat, rep, global)
146 : char *string, *pat, *rep;
147 : int global;
148 : {
149 0 : int patlen, replen, templen, tempsize, repl, i;
150 0 : char *temp, *r;
151 :
152 0 : patlen = strlen (pat);
153 0 : replen = strlen (rep);
154 0 : for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
155 : {
156 0 : if (repl && STREQN (string + i, pat, patlen))
157 : {
158 0 : if (replen)
159 0 : RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2));
160 :
161 0 : for (r = rep; *r; ) /* can rep == "" */
162 0 : temp[templen++] = *r++;
163 :
164 0 : i += patlen ? patlen : 1; /* avoid infinite recursion */
165 0 : repl = global != 0;
166 : }
167 : else
168 : {
169 0 : RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 16);
170 0 : temp[templen++] = string[i++];
171 : }
172 : }
173 0 : if (temp)
174 0 : temp[templen] = 0;
175 : else
176 0 : temp = savestring (string);
177 0 : return (temp);
178 : }
179 :
180 : /* Replace all instances of C in STRING with TEXT. TEXT may be empty or
181 : NULL. If DO_GLOB is non-zero, we quote the replacement text for
182 : globbing. Backslash may be used to quote C. */
183 : char *
184 0 : strcreplace (string, c, text, do_glob)
185 : char *string;
186 : int c;
187 : const char *text;
188 : int do_glob;
189 : {
190 0 : char *ret, *p, *r, *t;
191 0 : int len, rlen, ind, tlen;
192 :
193 0 : len = STRLEN (text);
194 0 : rlen = len + strlen (string) + 2;
195 0 : ret = (char *)xmalloc (rlen);
196 :
197 0 : for (p = string, r = ret; p && *p; )
198 : {
199 0 : if (*p == c)
200 : {
201 0 : if (len)
202 : {
203 0 : ind = r - ret;
204 0 : if (do_glob && (glob_pattern_p (text) || strchr (text, '\\')))
205 : {
206 0 : t = quote_globbing_chars (text);
207 0 : tlen = strlen (t);
208 0 : RESIZE_MALLOCED_BUFFER (ret, ind, tlen, rlen, rlen);
209 0 : r = ret + ind; /* in case reallocated */
210 0 : strcpy (r, t);
211 0 : r += tlen;
212 0 : free (t);
213 : }
214 : else
215 : {
216 0 : RESIZE_MALLOCED_BUFFER (ret, ind, len, rlen, rlen);
217 0 : r = ret + ind; /* in case reallocated */
218 0 : strcpy (r, text);
219 0 : r += len;
220 : }
221 : }
222 0 : p++;
223 0 : continue;
224 : }
225 :
226 0 : if (*p == '\\' && p[1] == c)
227 0 : p++;
228 :
229 0 : ind = r - ret;
230 0 : RESIZE_MALLOCED_BUFFER (ret, ind, 2, rlen, rlen);
231 0 : r = ret + ind; /* in case reallocated */
232 0 : *r++ = *p++;
233 : }
234 0 : *r = '\0';
235 :
236 0 : return ret;
237 : }
238 :
239 : #ifdef INCLUDE_UNUSED
240 : /* Remove all leading whitespace from STRING. This includes
241 : newlines. STRING should be terminated with a zero. */
242 : void
243 : strip_leading (string)
244 : char *string;
245 : {
246 : char *start = string;
247 :
248 : while (*string && (whitespace (*string) || *string == '\n'))
249 : string++;
250 :
251 : if (string != start)
252 : {
253 : int len = strlen (string);
254 : FASTCOPY (string, start, len);
255 : start[len] = '\0';
256 : }
257 : }
258 : #endif
259 :
260 : /* Remove all trailing whitespace from STRING. This includes
261 : newlines. If NEWLINES_ONLY is non-zero, only trailing newlines
262 : are removed. STRING should be terminated with a zero. */
263 : void
264 0 : strip_trailing (string, len, newlines_only)
265 : char *string;
266 : int len;
267 : int newlines_only;
268 : {
269 0 : while (len >= 0)
270 : {
271 0 : if ((newlines_only && string[len] == '\n') ||
272 0 : (!newlines_only && whitespace (string[len])))
273 0 : len--;
274 : else
275 : break;
276 : }
277 0 : string[len + 1] = '\0';
278 0 : }
279 :
280 : /* A wrapper for bcopy that can be prototyped in general.h */
281 : void
282 36603915 : xbcopy (s, d, n)
283 : char *s, *d;
284 : int n;
285 : {
286 36603915 : FASTCOPY (s, d, n);
287 36603915 : }
|