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, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #include "bashtypes.h"
26 #if defined (HAVE_UNISTD_H)
37 # define to_upper(c) (islower(c) ? toupper(c) : (c))
38 # define to_lower(c) (isupper(c) ? tolower(c) : (c))
41 /* Convert STRING by expanding the escape sequences specified by the
42 ANSI C standard. If SAWC is non-null, recognize `\c' and use that
43 as a string terminator. If we see \c, set *SAWC to 1 before
44 returning. LEN is the length of STRING. */
46 ansicstr (string, len, sawc, rlen)
48 int len, *sawc, *rlen;
53 if (string == 0 || *string == '\0')
54 return ((char *)NULL);
56 ret = xmalloc (len + 1);
57 for (r = ret, s = string; s && *s; )
60 if (c != '\\' || *s == '\0')
66 #if defined (__STDC__)
67 case 'a': c = '\a'; break;
68 case 'v': c = '\v'; break;
70 case 'a': c = '\007'; break;
71 case 'v': c = (int) 0x0B; break;
73 case 'b': c = '\b'; break;
74 case 'e': c = '\033'; break; /* ESC -- non-ANSI */
75 case 'E': c = '\033'; break; /* ESC -- non-ANSI */
76 case 'f': c = '\f'; break;
77 case 'n': c = '\n'; break;
78 case 'r': c = '\r'; break;
79 case 't': c = '\t'; break;
80 case '0': case '1': case '2': case '3':
81 case '4': case '5': case '6': case '7':
83 if (*s >= '0' && *s <= '7')
84 c = c * 8 + (*s++ - '0');
85 if (*s >= '0' && *s <= '7')
86 c = c * 8 + (*s++ - '0');
100 default: *r++ = '\\'; break;
111 /* **************************************************************** */
113 /* Functions to manage arrays of strings */
115 /* **************************************************************** */
117 /* Find NAME in ARRAY. Return the index of NAME, or -1 if not present.
118 ARRAY should be NULL terminated. */
120 find_name_in_array (name, array)
125 for (i = 0; array[i]; i++)
126 if (STREQ (name, array[i]))
132 /* Return the length of ARRAY, a NULL terminated array of char *. */
139 for (i = 0; array[i]; i++);
143 /* Free the contents of ARRAY, a NULL terminated array of char *. */
145 free_array_members (array)
153 for (i = 0; array[i]; i++)
164 free_array_members (array);
168 /* Allocate and return a new copy of ARRAY and its contents. */
177 len = array_len (array);
179 new_array = (char **)xmalloc ((len + 1) * sizeof (char *));
180 for (i = 0; array[i]; i++)
181 new_array[i] = savestring (array[i]);
182 new_array[i] = (char *)NULL;
187 /* Comparison routine for use with qsort() on arrays of strings. Uses
188 strcoll(3) if available, otherwise it uses strcmp(3). */
190 qsort_string_compare (s1, s2)
191 register char **s1, **s2;
193 #if defined (HAVE_STRCOLL)
194 return (strcoll (*s1, *s2));
195 #else /* !HAVE_STRCOLL */
198 if ((result = **s1 - **s2) == 0)
199 result = strcmp (*s1, *s2);
202 #endif /* !HAVE_STRCOLL */
205 /* Sort ARRAY, a null terminated array of pointers to strings. */
207 sort_char_array (array)
210 qsort (array, array_len (array), sizeof (char *),
211 (Function *)qsort_string_compare);
214 /* Cons up a new array of words. The words are taken from LIST,
215 which is a WORD_LIST *. If COPY is true, everything is malloc'ed,
216 so you should free everything in this array when you are done.
217 The array is NULL terminated. If IP is non-null, it gets the
218 number of words in the returned array. STARTING_INDEX says where
219 to start filling in the returned array; it can be used to reserve
220 space at the beginning of the array. */
222 word_list_to_argv (list, copy, starting_index, ip)
224 int copy, starting_index, *ip;
229 count = list_length (list);
230 array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
232 for (count = 0; count < starting_index; count++)
233 array[count] = (char *)NULL;
234 for (count = starting_index; list; count++, list = list->next)
235 array[count] = copy ? savestring (list->word->word) : list->word->word;
236 array[count] = (char *)NULL;
243 /* Convert an array of strings into the form used internally by the shell.
244 COPY means to copy the values in ARRAY into the returned list rather
245 than allocate new storage. STARTING_INDEX says where in ARRAY to begin. */
247 argv_to_word_list (array, copy, starting_index)
249 int copy, starting_index;
255 if (array == 0 || array[0] == 0)
256 return (WORD_LIST *)NULL;
258 for (count = 0; array[count]; count++)
261 for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
263 w = make_bare_word (copy ? "" : array[i]);
269 list = make_word_list (w, list);
271 return (REVERSE_LIST(list, WORD_LIST *));
274 /* **************************************************************** */
276 /* String Management Functions */
278 /* **************************************************************** */
280 /* Replace occurrences of PAT with REP in STRING. If GLOBAL is non-zero,
281 replace all occurrences, otherwise replace only the first.
282 This returns a new string; the caller should free it. */
284 strsub (string, pat, rep, global)
285 char *string, *pat, *rep;
288 int patlen, templen, tempsize, repl, i;
291 patlen = strlen (pat);
292 for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
294 if (repl && STREQN (string + i, pat, patlen))
296 RESIZE_MALLOCED_BUFFER (temp, templen, patlen, tempsize, (patlen * 2));
299 temp[templen++] = *r++;
306 RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 16);
307 temp[templen++] = string[i++];
314 #ifdef INCLUDE_UNUSED
315 /* Remove all leading whitespace from STRING. This includes
316 newlines. STRING should be terminated with a zero. */
318 strip_leading (string)
321 char *start = string;
323 while (*string && (whitespace (*string) || *string == '\n'))
328 int len = strlen (string);
329 FASTCOPY (string, start, len);
335 /* Remove all trailing whitespace from STRING. This includes
336 newlines. If NEWLINES_ONLY is non-zero, only trailing newlines
337 are removed. STRING should be terminated with a zero. */
339 strip_trailing (string, len, newlines_only)
346 if ((newlines_only && string[len] == '\n') ||
347 (!newlines_only && whitespace (string[len])))
352 string[len + 1] = '\0';
355 /* Determine if s2 occurs in s1. If so, return a pointer to the
356 match in s1. The compare is case insensitive. This is a
357 case-insensitive strstr(3). */
362 register int i, l, len, c;
364 c = to_upper (s2[0]);
365 for (i = 0, len = strlen (s1), l = strlen (s2); (len - i) >= l; i++)
366 if ((to_upper (s1[i]) == c) && (strncasecmp (s1 + i, s2, l) == 0))
368 return ((char *)NULL);
371 /* A wrapper for bcopy that can be prototyped in general.h */