blob: 97280cf5a843c957be9aa7b63401f26d43e4d995 [file] [log] [blame]
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001/* stringlib.c - Miscellaneous string functions. */
2
Jari Aalto7117c2d2002-07-17 14:10:11 +00003/* Copyright (C) 1996-2002 Free Software Foundation, Inc.
Jari Aaltoccc6cda1996-12-23 17:02:34 +00004
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
Jari Aaltobb706242000-03-17 21:46:59 +000019 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +000020
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>
Jari Aaltof73dda02001-11-13 17:56:06 +000031#include "chartypes.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000032
33#include "shell.h"
Jari Aaltobb706242000-03-17 21:46:59 +000034#include "pathexp.h"
35
Jari Aaltof73dda02001-11-13 17:56:06 +000036#include <glob/glob.h>
37
Jari Aaltobb706242000-03-17 21:46:59 +000038#if defined (EXTENDED_GLOB)
Jari Aaltof73dda02001-11-13 17:56:06 +000039# include <glob/strmatch.h>
Jari Aaltobb706242000-03-17 21:46:59 +000040#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000041
Jari Aaltoccc6cda1996-12-23 17:02:34 +000042/* **************************************************************** */
43/* */
44/* Functions to manage arrays of strings */
45/* */
46/* **************************************************************** */
47
Jari Aaltobb706242000-03-17 21:46:59 +000048/* Find STRING in ALIST, a list of string key/int value pairs. If FLAGS
Jari Aaltof73dda02001-11-13 17:56:06 +000049 is 1, STRING is treated as a pattern and matched using strmatch. */
Jari Aaltobb706242000-03-17 21:46:59 +000050int
51find_string_in_alist (string, alist, flags)
52 char *string;
53 STRING_INT_ALIST *alist;
54 int flags;
55{
56 register int i;
57 int r;
58
59 for (i = r = 0; alist[i].word; i++)
60 {
61#if defined (EXTENDED_GLOB)
62 if (flags)
Jari Aaltof73dda02001-11-13 17:56:06 +000063 r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
Jari Aaltobb706242000-03-17 21:46:59 +000064 else
65#endif
Jari Aalto28ef6c32001-04-06 19:14:31 +000066 r = STREQ (string, alist[i].word);
Jari Aaltobb706242000-03-17 21:46:59 +000067
68 if (r)
Jari Aalto28ef6c32001-04-06 19:14:31 +000069 return (alist[i].token);
Jari Aaltobb706242000-03-17 21:46:59 +000070 }
71 return -1;
72}
73
Jari Aalto7117c2d2002-07-17 14:10:11 +000074/* 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. */
77char *
78find_token_in_alist (token, alist, flags)
79 int token;
80 STRING_INT_ALIST *alist;
81 int flags;
82{
83 register int i;
84
85 for (i = 0; alist[i].word; i++)
86 {
87 if (alist[i].token == token)
88 return (savestring (alist[i].word));
89 }
90 return ((char *)NULL);
91}
92
93int
94find_index_in_alist (string, alist, flags)
95 char *string;
96 STRING_INT_ALIST *alist;
97 int flags;
98{
99 register int i;
100 int r;
101
102 for (i = r = 0; alist[i].word; i++)
103 {
104#if defined (EXTENDED_GLOB)
105 if (flags)
106 r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
107 else
108#endif
109 r = STREQ (string, alist[i].word);
110
111 if (r)
112 return (i);
113 }
114
115 return -1;
116}
117
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000118/* **************************************************************** */
119/* */
120/* String Management Functions */
121/* */
122/* **************************************************************** */
123
Jari Aalto7117c2d2002-07-17 14:10:11 +0000124/* Cons a new string from STRING starting at START and ending at END,
125 not including END. */
126char *
127substring (string, start, end)
128 char *string;
129 int start, end;
130{
131 register int len;
132 register char *result;
133
134 len = end - start;
135 result = (char *)xmalloc (len + 1);
136 strncpy (result, string + start, len);
137 result[len] = '\0';
138 return (result);
139}
140
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000141/* 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. */
144char *
145strsub (string, pat, rep, global)
146 char *string, *pat, *rep;
147 int global;
148{
Jari Aaltocce855b1998-04-17 19:52:44 +0000149 int patlen, replen, templen, tempsize, repl, i;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000150 char *temp, *r;
151
152 patlen = strlen (pat);
Jari Aaltocce855b1998-04-17 19:52:44 +0000153 replen = strlen (rep);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000154 for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
155 {
156 if (repl && STREQN (string + i, pat, patlen))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000157 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000158 if (replen)
159 RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000160
161 for (r = rep; *r; )
162 temp[templen++] = *r++;
163
Jari Aaltof73dda02001-11-13 17:56:06 +0000164 i += patlen ? patlen : 1; /* avoid infinite recursion */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000165 repl = global != 0;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000166 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000167 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
Jari Aaltobb706242000-03-17 21:46:59 +0000177/* 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. */
180char *
181strcreplace (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;
Jari Aaltof73dda02001-11-13 17:56:06 +0000192 ret = (char *)xmalloc (rlen);
Jari Aaltobb706242000-03-17 21:46:59 +0000193
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
Jari Aalto28ef6c32001-04-06 19:14:31 +0000223 if (*p == '\\' && p[1] == c)
Jari Aaltobb706242000-03-17 21:46:59 +0000224 p++;
225
Jari Aaltof73dda02001-11-13 17:56:06 +0000226 ind = r - ret;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000227 RESIZE_MALLOCED_BUFFER (ret, ind, 2, rlen, rlen);
228 r = ret + ind; /* in case reallocated */
Jari Aaltobb706242000-03-17 21:46:59 +0000229 *r++ = *p++;
230 }
231 *r = '\0';
232
233 return ret;
234}
235
Jari Aaltod166f041997-06-05 14:59:13 +0000236#ifdef INCLUDE_UNUSED
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000237/* Remove all leading whitespace from STRING. This includes
238 newlines. STRING should be terminated with a zero. */
239void
240strip_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}
Jari Aaltod166f041997-06-05 14:59:13 +0000255#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000256
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. */
260void
Jari Aaltod166f041997-06-05 14:59:13 +0000261strip_trailing (string, len, newlines_only)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000262 char *string;
Jari Aaltod166f041997-06-05 14:59:13 +0000263 int len;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000264 int newlines_only;
265{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000266 while (len >= 0)
267 {
268 if ((newlines_only && string[len] == '\n') ||
Jari Aalto28ef6c32001-04-06 19:14:31 +0000269 (!newlines_only && whitespace (string[len])))
270 len--;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000271 else
Jari Aalto28ef6c32001-04-06 19:14:31 +0000272 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000273 }
274 string[len + 1] = '\0';
275}
276
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000277/* A wrapper for bcopy that can be prototyped in general.h */
278void
279xbcopy (s, d, n)
280 char *s, *d;
281 int n;
282{
283 FASTCOPY (s, d, n);
284}