]> git.ipfire.org Git - thirdparty/bash.git/blame - stringlib.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / stringlib.c
CommitLineData
ccc6cda3
JA
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
bb70624e 20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
ccc6cda3
JA
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"
bb70624e
JA
35#include "pathexp.h"
36
37#if defined (EXTENDED_GLOB)
38# include <glob/fnmatch.h>
39#endif
ccc6cda3 40
ccc6cda3
JA
41/* **************************************************************** */
42/* */
43/* Functions to manage arrays of strings */
44/* */
45/* **************************************************************** */
46
ccc6cda3
JA
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. */
54char **
55word_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. */
79WORD_LIST *
80argv_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
bb70624e
JA
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. */
109int
110find_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)
28ef6c31 122 r = fnmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
bb70624e
JA
123 else
124#endif
28ef6c31 125 r = STREQ (string, alist[i].word);
bb70624e
JA
126
127 if (r)
28ef6c31 128 return (alist[i].token);
bb70624e
JA
129 }
130 return -1;
131}
132
ccc6cda3
JA
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. */
142char *
143strsub (string, pat, rep, global)
144 char *string, *pat, *rep;
145 int global;
146{
cce855bc 147 int patlen, replen, templen, tempsize, repl, i;
ccc6cda3
JA
148 char *temp, *r;
149
150 patlen = strlen (pat);
cce855bc 151 replen = strlen (rep);
ccc6cda3
JA
152 for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
153 {
154 if (repl && STREQN (string + i, pat, patlen))
28ef6c31
JA
155 {
156 RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2));
ccc6cda3
JA
157
158 for (r = rep; *r; )
159 temp[templen++] = *r++;
160
161 i += patlen;
162 repl = global != 0;
28ef6c31 163 }
ccc6cda3
JA
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
bb70624e
JA
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. */
177char *
178strcreplace (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
28ef6c31 220 if (*p == '\\' && p[1] == c)
bb70624e
JA
221 p++;
222
28ef6c31
JA
223 RESIZE_MALLOCED_BUFFER (ret, ind, 2, rlen, rlen);
224 r = ret + ind; /* in case reallocated */
bb70624e
JA
225 *r++ = *p++;
226 }
227 *r = '\0';
228
229 return ret;
230}
231
d166f048 232#ifdef INCLUDE_UNUSED
ccc6cda3
JA
233/* Remove all leading whitespace from STRING. This includes
234 newlines. STRING should be terminated with a zero. */
235void
236strip_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}
d166f048 251#endif
ccc6cda3
JA
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. */
256void
d166f048 257strip_trailing (string, len, newlines_only)
ccc6cda3 258 char *string;
d166f048 259 int len;
ccc6cda3
JA
260 int newlines_only;
261{
ccc6cda3
JA
262 while (len >= 0)
263 {
264 if ((newlines_only && string[len] == '\n') ||
28ef6c31
JA
265 (!newlines_only && whitespace (string[len])))
266 len--;
ccc6cda3 267 else
28ef6c31 268 break;
ccc6cda3
JA
269 }
270 string[len + 1] = '\0';
271}
272
ccc6cda3
JA
273/* A wrapper for bcopy that can be prototyped in general.h */
274void
275xbcopy (s, d, n)
276 char *s, *d;
277 int n;
278{
279 FASTCOPY (s, d, n);
280}