]> git.ipfire.org Git - thirdparty/bash.git/blob - stringlib.c
Imported from ../bash-2.02.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, 675 Mass Ave, Cambridge, MA 02139, 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
36 #ifndef to_upper
37 # define to_upper(c) (islower(c) ? toupper(c) : (c))
38 # define to_lower(c) (isupper(c) ? tolower(c) : (c))
39 #endif
40
41 #define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
42 #define OCTVALUE(c) ((c) - '0')
43
44 #ifndef isxdigit
45 # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
46 #endif
47
48 #define HEXVALUE(c) \
49 ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
50
51 /* Convert STRING by expanding the escape sequences specified by the
52 ANSI C standard. If SAWC is non-null, recognize `\c' and use that
53 as a string terminator. If we see \c, set *SAWC to 1 before
54 returning. LEN is the length of STRING. */
55 char *
56 ansicstr (string, len, sawc, rlen)
57 char *string;
58 int len, *sawc, *rlen;
59 {
60 int c, temp;
61 char *ret, *r, *s;
62
63 if (string == 0 || *string == '\0')
64 return ((char *)NULL);
65
66 ret = xmalloc (len + 1);
67 for (r = ret, s = string; s && *s; )
68 {
69 c = *s++;
70 if (c != '\\' || *s == '\0')
71 *r++ = c;
72 else
73 {
74 switch (c = *s++)
75 {
76 #if defined (__STDC__)
77 case 'a': c = '\a'; break;
78 case 'v': c = '\v'; break;
79 #else
80 case 'a': c = '\007'; break;
81 case 'v': c = (int) 0x0B; break;
82 #endif
83 case 'b': c = '\b'; break;
84 case 'e': case 'E': /* ESC -- non-ANSI */
85 c = '\033'; break;
86 case 'f': c = '\f'; break;
87 case 'n': c = '\n'; break;
88 case 'r': c = '\r'; break;
89 case 't': c = '\t'; break;
90 case '0': case '1': case '2': case '3':
91 case '4': case '5': case '6': case '7':
92 for (temp = 2, c -= '0'; ISOCTAL (*s) && temp--; s++)
93 c = (c * 8) + OCTVALUE (*s);
94 break;
95 case 'x': /* Hex digit -- non-ANSI */
96 for (temp = 3, c = 0; isxdigit (*s) && temp--; s++)
97 c = (c * 16) + HEXVALUE (*s);
98 /* \x followed by non-hex digits is passed through unchanged */
99 if (temp == 3)
100 {
101 *r++ = '\\';
102 c = 'x';
103 }
104 break;
105 case '\\':
106 case '\'':
107 break;
108 case 'c':
109 if (sawc)
110 {
111 *sawc = 1;
112 *r = '\0';
113 if (rlen)
114 *rlen = r - ret;
115 return ret;
116 }
117 default: *r++ = '\\'; break;
118 }
119 *r++ = c;
120 }
121 }
122 *r = '\0';
123 if (rlen)
124 *rlen = r - ret;
125 return ret;
126 }
127
128 /* **************************************************************** */
129 /* */
130 /* Functions to manage arrays of strings */
131 /* */
132 /* **************************************************************** */
133
134 #ifdef INCLUDE_UNUSED
135 /* Find NAME in ARRAY. Return the index of NAME, or -1 if not present.
136 ARRAY should be NULL terminated. */
137 int
138 find_name_in_array (name, array)
139 char *name, **array;
140 {
141 int i;
142
143 for (i = 0; array[i]; i++)
144 if (STREQ (name, array[i]))
145 return (i);
146
147 return (-1);
148 }
149 #endif
150
151 /* Return the length of ARRAY, a NULL terminated array of char *. */
152 int
153 array_len (array)
154 char **array;
155 {
156 register int i;
157
158 for (i = 0; array[i]; i++);
159 return (i);
160 }
161
162 /* Free the contents of ARRAY, a NULL terminated array of char *. */
163 void
164 free_array_members (array)
165 char **array;
166 {
167 register int i;
168
169 if (array == 0)
170 return;
171
172 for (i = 0; array[i]; i++)
173 free (array[i]);
174 }
175
176 void
177 free_array (array)
178 char **array;
179 {
180 if (array == 0)
181 return;
182
183 free_array_members (array);
184 free (array);
185 }
186
187 /* Allocate and return a new copy of ARRAY and its contents. */
188 char **
189 copy_array (array)
190 char **array;
191 {
192 register int i;
193 int len;
194 char **new_array;
195
196 len = array_len (array);
197
198 new_array = (char **)xmalloc ((len + 1) * sizeof (char *));
199 for (i = 0; array[i]; i++)
200 new_array[i] = savestring (array[i]);
201 new_array[i] = (char *)NULL;
202
203 return (new_array);
204 }
205
206 /* Comparison routine for use with qsort() on arrays of strings. Uses
207 strcoll(3) if available, otherwise it uses strcmp(3). */
208 int
209 qsort_string_compare (s1, s2)
210 register char **s1, **s2;
211 {
212 #if defined (HAVE_STRCOLL)
213 return (strcoll (*s1, *s2));
214 #else /* !HAVE_STRCOLL */
215 int result;
216
217 if ((result = **s1 - **s2) == 0)
218 result = strcmp (*s1, *s2);
219
220 return (result);
221 #endif /* !HAVE_STRCOLL */
222 }
223
224 /* Sort ARRAY, a null terminated array of pointers to strings. */
225 void
226 sort_char_array (array)
227 char **array;
228 {
229 qsort (array, array_len (array), sizeof (char *),
230 (Function *)qsort_string_compare);
231 }
232
233 /* Cons up a new array of words. The words are taken from LIST,
234 which is a WORD_LIST *. If COPY is true, everything is malloc'ed,
235 so you should free everything in this array when you are done.
236 The array is NULL terminated. If IP is non-null, it gets the
237 number of words in the returned array. STARTING_INDEX says where
238 to start filling in the returned array; it can be used to reserve
239 space at the beginning of the array. */
240 char **
241 word_list_to_argv (list, copy, starting_index, ip)
242 WORD_LIST *list;
243 int copy, starting_index, *ip;
244 {
245 int count;
246 char **array;
247
248 count = list_length (list);
249 array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
250
251 for (count = 0; count < starting_index; count++)
252 array[count] = (char *)NULL;
253 for (count = starting_index; list; count++, list = list->next)
254 array[count] = copy ? savestring (list->word->word) : list->word->word;
255 array[count] = (char *)NULL;
256
257 if (ip)
258 *ip = count;
259 return (array);
260 }
261
262 /* Convert an array of strings into the form used internally by the shell.
263 COPY means to copy the values in ARRAY into the returned list rather
264 than allocate new storage. STARTING_INDEX says where in ARRAY to begin. */
265 WORD_LIST *
266 argv_to_word_list (array, copy, starting_index)
267 char **array;
268 int copy, starting_index;
269 {
270 WORD_LIST *list;
271 WORD_DESC *w;
272 int i, count;
273
274 if (array == 0 || array[0] == 0)
275 return (WORD_LIST *)NULL;
276
277 for (count = 0; array[count]; count++)
278 ;
279
280 for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
281 {
282 w = make_bare_word (copy ? "" : array[i]);
283 if (copy)
284 {
285 free (w->word);
286 w->word = array[i];
287 }
288 list = make_word_list (w, list);
289 }
290 return (REVERSE_LIST(list, WORD_LIST *));
291 }
292
293 /* **************************************************************** */
294 /* */
295 /* String Management Functions */
296 /* */
297 /* **************************************************************** */
298
299 /* Replace occurrences of PAT with REP in STRING. If GLOBAL is non-zero,
300 replace all occurrences, otherwise replace only the first.
301 This returns a new string; the caller should free it. */
302 char *
303 strsub (string, pat, rep, global)
304 char *string, *pat, *rep;
305 int global;
306 {
307 int patlen, replen, templen, tempsize, repl, i;
308 char *temp, *r;
309
310 patlen = strlen (pat);
311 replen = strlen (rep);
312 for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
313 {
314 if (repl && STREQN (string + i, pat, patlen))
315 {
316 RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2));
317
318 for (r = rep; *r; )
319 temp[templen++] = *r++;
320
321 i += patlen;
322 repl = global != 0;
323 }
324 else
325 {
326 RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 16);
327 temp[templen++] = string[i++];
328 }
329 }
330 temp[templen] = 0;
331 return (temp);
332 }
333
334 #ifdef INCLUDE_UNUSED
335 /* Remove all leading whitespace from STRING. This includes
336 newlines. STRING should be terminated with a zero. */
337 void
338 strip_leading (string)
339 char *string;
340 {
341 char *start = string;
342
343 while (*string && (whitespace (*string) || *string == '\n'))
344 string++;
345
346 if (string != start)
347 {
348 int len = strlen (string);
349 FASTCOPY (string, start, len);
350 start[len] = '\0';
351 }
352 }
353 #endif
354
355 /* Remove all trailing whitespace from STRING. This includes
356 newlines. If NEWLINES_ONLY is non-zero, only trailing newlines
357 are removed. STRING should be terminated with a zero. */
358 void
359 strip_trailing (string, len, newlines_only)
360 char *string;
361 int len;
362 int newlines_only;
363 {
364 while (len >= 0)
365 {
366 if ((newlines_only && string[len] == '\n') ||
367 (!newlines_only && whitespace (string[len])))
368 len--;
369 else
370 break;
371 }
372 string[len + 1] = '\0';
373 }
374
375 /* Determine if s2 occurs in s1. If so, return a pointer to the
376 match in s1. The compare is case insensitive. This is a
377 case-insensitive strstr(3). */
378 char *
379 strindex (s1, s2)
380 char *s1, *s2;
381 {
382 register int i, l, len, c;
383
384 c = to_upper (s2[0]);
385 for (i = 0, len = strlen (s1), l = strlen (s2); (len - i) >= l; i++)
386 if ((to_upper (s1[i]) == c) && (strncasecmp (s1 + i, s2, l) == 0))
387 return (s1 + i);
388 return ((char *)NULL);
389 }
390
391 /* A wrapper for bcopy that can be prototyped in general.h */
392 void
393 xbcopy (s, d, n)
394 char *s, *d;
395 int n;
396 {
397 FASTCOPY (s, d, n);
398 }