1 /* stringlib.c - Miscellaneous string functions. */
4 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
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
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
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. */
24 #include "bashtypes.h"
26 #if defined (HAVE_UNISTD_H)
37 #if defined (EXTENDED_GLOB)
38 # include <glob/fnmatch.h>
42 # define to_upper(c) (islower(c) ? toupper(c) : (c))
43 # define to_lower(c) (isupper(c) ? tolower(c) : (c))
46 #define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
47 #define OCTVALUE(c) ((c) - '0')
50 # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
54 ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
56 /* Convert STRING by expanding the escape sequences specified by the
57 ANSI C standard. If SAWC is non-null, recognize `\c' and use that
58 as a string terminator. If we see \c, set *SAWC to 1 before
59 returning. LEN is the length of STRING. FOR_ECHO is a flag that
60 means, if non-zero, that we're translating a string for `echo -e',
61 and therefore should not treat a single quote as a character that
62 may be escaped with a backslash. */
64 ansicstr (string, len, for_echo, sawc, rlen)
66 int len, for_echo, *sawc, *rlen;
71 if (string == 0 || *string == '\0')
72 return ((char *)NULL);
74 ret = xmalloc (len + 1);
75 for (r = ret, s = string; s && *s; )
78 if (c != '\\' || *s == '\0')
84 #if defined (__STDC__)
85 case 'a': c = '\a'; break;
86 case 'v': c = '\v'; break;
88 case 'a': c = '\007'; break;
89 case 'v': c = (int) 0x0B; break;
91 case 'b': c = '\b'; break;
92 case 'e': case 'E': /* ESC -- non-ANSI */
94 case 'f': c = '\f'; break;
95 case 'n': c = '\n'; break;
96 case 'r': c = '\r'; break;
97 case 't': c = '\t'; break;
98 case '0': case '1': case '2': case '3':
99 case '4': case '5': case '6': case '7':
100 for (temp = 2, c -= '0'; ISOCTAL (*s) && temp--; s++)
101 c = (c * 8) + OCTVALUE (*s);
103 case 'x': /* Hex digit -- non-ANSI */
104 for (temp = 3, c = 0; isxdigit (*s) && temp--; s++)
105 c = (c * 16) + HEXVALUE (*s);
106 /* \x followed by non-hex digits is passed through unchanged */
128 default: *r++ = '\\'; break;
139 /* **************************************************************** */
141 /* Functions to manage arrays of strings */
143 /* **************************************************************** */
145 #ifdef INCLUDE_UNUSED
146 /* Find NAME in ARRAY. Return the index of NAME, or -1 if not present.
147 ARRAY should be NULL terminated. */
149 find_name_in_array (name, array)
154 for (i = 0; array[i]; i++)
155 if (STREQ (name, array[i]))
162 /* Allocate an array of strings with room for N members. */
167 return ((char **)xmalloc ((n) * sizeof (char *)));
170 /* Return the length of ARRAY, a NULL terminated array of char *. */
177 for (i = 0; array[i]; i++);
181 /* Free the contents of ARRAY, a NULL terminated array of char *. */
183 free_array_members (array)
191 for (i = 0; array[i]; i++)
202 free_array_members (array);
206 /* Allocate and return a new copy of ARRAY and its contents. */
215 len = array_len (array);
217 new_array = (char **)xmalloc ((len + 1) * sizeof (char *));
218 for (i = 0; array[i]; i++)
219 new_array[i] = savestring (array[i]);
220 new_array[i] = (char *)NULL;
225 /* Comparison routine for use with qsort() on arrays of strings. Uses
226 strcoll(3) if available, otherwise it uses strcmp(3). */
228 qsort_string_compare (s1, s2)
229 register char **s1, **s2;
231 #if defined (HAVE_STRCOLL)
232 return (strcoll (*s1, *s2));
233 #else /* !HAVE_STRCOLL */
236 if ((result = **s1 - **s2) == 0)
237 result = strcmp (*s1, *s2);
240 #endif /* !HAVE_STRCOLL */
243 /* Sort ARRAY, a null terminated array of pointers to strings. */
245 sort_char_array (array)
248 qsort (array, array_len (array), sizeof (char *),
249 (Function *)qsort_string_compare);
252 /* Cons up a new array of words. The words are taken from LIST,
253 which is a WORD_LIST *. If COPY is true, everything is malloc'ed,
254 so you should free everything in this array when you are done.
255 The array is NULL terminated. If IP is non-null, it gets the
256 number of words in the returned array. STARTING_INDEX says where
257 to start filling in the returned array; it can be used to reserve
258 space at the beginning of the array. */
260 word_list_to_argv (list, copy, starting_index, ip)
262 int copy, starting_index, *ip;
267 count = list_length (list);
268 array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
270 for (count = 0; count < starting_index; count++)
271 array[count] = (char *)NULL;
272 for (count = starting_index; list; count++, list = list->next)
273 array[count] = copy ? savestring (list->word->word) : list->word->word;
274 array[count] = (char *)NULL;
281 /* Convert an array of strings into the form used internally by the shell.
282 COPY means to copy the values in ARRAY into the returned list rather
283 than allocate new storage. STARTING_INDEX says where in ARRAY to begin. */
285 argv_to_word_list (array, copy, starting_index)
287 int copy, starting_index;
293 if (array == 0 || array[0] == 0)
294 return (WORD_LIST *)NULL;
296 for (count = 0; array[count]; count++)
299 for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
301 w = make_bare_word (copy ? "" : array[i]);
307 list = make_word_list (w, list);
309 return (REVERSE_LIST(list, WORD_LIST *));
312 /* Find STRING in ALIST, a list of string key/int value pairs. If FLAGS
313 is 1, STRING is treated as a pattern and matched using fnmatch. */
315 find_string_in_alist (string, alist, flags)
317 STRING_INT_ALIST *alist;
323 for (i = r = 0; alist[i].word; i++)
325 #if defined (EXTENDED_GLOB)
327 r = fnmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
330 r = STREQ (string, alist[i].word);
333 return (alist[i].token);
338 /* **************************************************************** */
340 /* String Management Functions */
342 /* **************************************************************** */
344 /* Replace occurrences of PAT with REP in STRING. If GLOBAL is non-zero,
345 replace all occurrences, otherwise replace only the first.
346 This returns a new string; the caller should free it. */
348 strsub (string, pat, rep, global)
349 char *string, *pat, *rep;
352 int patlen, replen, templen, tempsize, repl, i;
355 patlen = strlen (pat);
356 replen = strlen (rep);
357 for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
359 if (repl && STREQN (string + i, pat, patlen))
361 RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2));
364 temp[templen++] = *r++;
371 RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 16);
372 temp[templen++] = string[i++];
379 /* Replace all instances of C in STRING with TEXT. TEXT may be empty or
380 NULL. If DO_GLOB is non-zero, we quote the replacement text for
381 globbing. Backslash may be used to quote C. */
383 strcreplace (string, c, text, do_glob)
389 char *ret, *p, *r, *t;
390 int len, rlen, ind, tlen;
393 rlen = len + strlen (string) + 2;
394 ret = xmalloc (rlen);
396 for (p = string, r = ret; p && *p; )
403 if (do_glob && (glob_pattern_p (text) || strchr (text, '\\')))
405 t = quote_globbing_chars (text);
407 RESIZE_MALLOCED_BUFFER (ret, ind, tlen, rlen, rlen);
408 r = ret + ind; /* in case reallocated */
415 RESIZE_MALLOCED_BUFFER (ret, ind, len, rlen, rlen);
416 r = ret + ind; /* in case reallocated */
425 if (*p == '\\' && p[1] == '&')
435 #ifdef INCLUDE_UNUSED
436 /* Remove all leading whitespace from STRING. This includes
437 newlines. STRING should be terminated with a zero. */
439 strip_leading (string)
442 char *start = string;
444 while (*string && (whitespace (*string) || *string == '\n'))
449 int len = strlen (string);
450 FASTCOPY (string, start, len);
456 /* Remove all trailing whitespace from STRING. This includes
457 newlines. If NEWLINES_ONLY is non-zero, only trailing newlines
458 are removed. STRING should be terminated with a zero. */
460 strip_trailing (string, len, newlines_only)
467 if ((newlines_only && string[len] == '\n') ||
468 (!newlines_only && whitespace (string[len])))
473 string[len + 1] = '\0';
476 /* Determine if s2 occurs in s1. If so, return a pointer to the
477 match in s1. The compare is case insensitive. This is a
478 case-insensitive strstr(3). */
483 register int i, l, len, c;
485 c = to_upper (s2[0]);
486 for (i = 0, len = strlen (s1), l = strlen (s2); (len - i) >= l; i++)
487 if ((to_upper (s1[i]) == c) && (strncasecmp (s1 + i, s2, l) == 0))
489 return ((char *)NULL);
492 /* A wrapper for bcopy that can be prototyped in general.h */