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