db8f15b3b1d6ec43d7b73cc3362f51a1f95e963c
[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, 59 Temple Place, Suite 330, Boston, MA 02111 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 "chartypes.h"
33
34 #include "shell.h"
35 #include "pathexp.h"
36
37 #include <glob/glob.h>
38
39 #if defined (EXTENDED_GLOB)
40 #  include <glob/strmatch.h>
41 #endif
42
43 /* **************************************************************** */
44 /*                                                                  */
45 /*              Functions to manage arrays of strings               */
46 /*                                                                  */
47 /* **************************************************************** */
48
49 /* Cons up a new array of words.  The words are taken from LIST,
50    which is a WORD_LIST *.  If COPY is true, everything is malloc'ed,
51    so you should free everything in this array when you are done.
52    The array is NULL terminated.  If IP is non-null, it gets the
53    number of words in the returned array.  STARTING_INDEX says where
54    to start filling in the returned array; it can be used to reserve
55    space at the beginning of the array. */
56 char **
57 word_list_to_argv (list, copy, starting_index, ip)
58      WORD_LIST *list;
59      int copy, starting_index, *ip;
60 {
61   int count;
62   char **array;
63
64   count = list_length (list);
65   array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
66
67   for (count = 0; count < starting_index; count++)
68     array[count] = (char *)NULL;
69   for (count = starting_index; list; count++, list = list->next)
70     array[count] = copy ? savestring (list->word->word) : list->word->word;
71   array[count] = (char *)NULL;
72
73   if (ip)
74     *ip = count;
75   return (array);
76 }
77
78 /* Convert an array of strings into the form used internally by the shell.
79    COPY means to copy the values in ARRAY into the returned list rather
80    than allocate new storage.  STARTING_INDEX says where in ARRAY to begin. */
81 WORD_LIST *
82 argv_to_word_list (array, copy, starting_index)
83      char **array;
84      int copy, starting_index;
85 {
86   WORD_LIST *list;
87   WORD_DESC *w;
88   int i, count;
89
90   if (array == 0 || array[0] == 0)
91     return (WORD_LIST *)NULL;
92
93   for (count = 0; array[count]; count++)
94     ;
95
96   for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
97     {
98       w = make_bare_word (copy ? "" : array[i]);
99       if (copy)
100         {
101           free (w->word);
102           w->word = array[i];
103         }
104       list = make_word_list (w, list);
105     }
106   return (REVERSE_LIST(list, WORD_LIST *));
107 }
108
109 /* Find STRING in ALIST, a list of string key/int value pairs.  If FLAGS
110    is 1, STRING is treated as a pattern and matched using strmatch. */
111 int
112 find_string_in_alist (string, alist, flags)
113      char *string;
114      STRING_INT_ALIST *alist;
115      int flags;
116 {
117   register int i;
118   int r;
119
120   for (i = r = 0; alist[i].word; i++)
121     {
122 #if defined (EXTENDED_GLOB)
123       if (flags)
124         r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
125       else
126 #endif
127         r = STREQ (string, alist[i].word);
128
129       if (r)
130         return (alist[i].token);
131     }
132   return -1;
133 }
134
135 /* **************************************************************** */
136 /*                                                                  */
137 /*                  String Management Functions                     */
138 /*                                                                  */
139 /* **************************************************************** */
140
141 /* 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. */
144 char *
145 strsub (string, pat, rep, global)
146      char *string, *pat, *rep;
147      int global;
148 {
149   int patlen, replen, templen, tempsize, repl, i;
150   char *temp, *r;
151
152   patlen = strlen (pat);
153   replen = strlen (rep);
154   for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
155     {
156       if (repl && STREQN (string + i, pat, patlen))
157         {
158           if (replen)
159             RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2));
160
161           for (r = rep; *r; )
162             temp[templen++] = *r++;
163
164           i += patlen ? patlen : 1;     /* avoid infinite recursion */
165           repl = global != 0;
166         }
167       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
177 /* 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. */
180 char *
181 strcreplace (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;
192   ret = (char *)xmalloc (rlen);
193
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
223       if (*p == '\\' && p[1] == c)
224         p++;
225
226       ind = r - ret;
227       RESIZE_MALLOCED_BUFFER (ret, ind, 2, rlen, rlen);
228       r = ret + ind;                    /* in case reallocated */
229       *r++ = *p++;
230     }
231   *r = '\0';
232
233   return ret;
234 }
235
236 #ifdef INCLUDE_UNUSED
237 /* Remove all leading whitespace from STRING.  This includes
238    newlines.  STRING should be terminated with a zero. */
239 void
240 strip_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 }
255 #endif
256
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. */
260 void
261 strip_trailing (string, len, newlines_only)
262      char *string;
263      int len;
264      int newlines_only;
265 {
266   while (len >= 0)
267     {
268       if ((newlines_only && string[len] == '\n') ||
269           (!newlines_only && whitespace (string[len])))
270         len--;
271       else
272         break;
273     }
274   string[len + 1] = '\0';
275 }
276
277 /* A wrapper for bcopy that can be prototyped in general.h */
278 void
279 xbcopy (s, d, n)
280      char *s, *d;
281      int n;
282 {
283   FASTCOPY (s, d, n);
284 }