blob: 471c8face11db05215bfc0c4e37cecefde60d065 [file] [log] [blame]
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001/* 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
Jari Aaltobb706242000-03-17 21:46:59 +000020 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +000021
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"
Jari Aaltobb706242000-03-17 21:46:59 +000035#include "pathexp.h"
36
37#if defined (EXTENDED_GLOB)
38# include <glob/fnmatch.h>
39#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000040
41#ifndef to_upper
42# define to_upper(c) (islower(c) ? toupper(c) : (c))
43# define to_lower(c) (isupper(c) ? tolower(c) : (c))
44#endif
45
Jari Aaltocce855b1998-04-17 19:52:44 +000046#define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
47#define OCTVALUE(c) ((c) - '0')
48
49#ifndef isxdigit
50# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
51#endif
52
53#define HEXVALUE(c) \
54 ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
55
Jari Aaltoccc6cda1996-12-23 17:02:34 +000056/* 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
Jari Aaltobb706242000-03-17 21:46:59 +000059 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. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +000063char *
Jari Aaltobb706242000-03-17 21:46:59 +000064ansicstr (string, len, for_echo, sawc, rlen)
Jari Aaltoccc6cda1996-12-23 17:02:34 +000065 char *string;
Jari Aaltobb706242000-03-17 21:46:59 +000066 int len, for_echo, *sawc, *rlen;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000067{
Jari Aaltocce855b1998-04-17 19:52:44 +000068 int c, temp;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000069 char *ret, *r, *s;
70
71 if (string == 0 || *string == '\0')
72 return ((char *)NULL);
73
74 ret = xmalloc (len + 1);
75 for (r = ret, s = string; s && *s; )
76 {
77 c = *s++;
78 if (c != '\\' || *s == '\0')
79 *r++ = c;
80 else
81 {
82 switch (c = *s++)
83 {
84#if defined (__STDC__)
85 case 'a': c = '\a'; break;
86 case 'v': c = '\v'; break;
87#else
88 case 'a': c = '\007'; break;
89 case 'v': c = (int) 0x0B; break;
90#endif
91 case 'b': c = '\b'; break;
Jari Aaltocce855b1998-04-17 19:52:44 +000092 case 'e': case 'E': /* ESC -- non-ANSI */
93 c = '\033'; break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000094 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':
Jari Aaltocce855b1998-04-17 19:52:44 +0000100 for (temp = 2, c -= '0'; ISOCTAL (*s) && temp--; s++)
101 c = (c * 8) + OCTVALUE (*s);
102 break;
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 */
107 if (temp == 3)
108 {
109 *r++ = '\\';
110 c = 'x';
111 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000112 break;
113 case '\\':
Jari Aaltobb706242000-03-17 21:46:59 +0000114 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000115 case '\'':
Jari Aaltobb706242000-03-17 21:46:59 +0000116 if (for_echo)
117 *r++ = '\\';
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000118 break;
119 case 'c':
120 if (sawc)
121 {
122 *sawc = 1;
123 *r = '\0';
Jari Aaltod166f041997-06-05 14:59:13 +0000124 if (rlen)
125 *rlen = r - ret;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000126 return ret;
127 }
128 default: *r++ = '\\'; break;
129 }
130 *r++ = c;
131 }
132 }
133 *r = '\0';
Jari Aaltod166f041997-06-05 14:59:13 +0000134 if (rlen)
135 *rlen = r - ret;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000136 return ret;
137}
138
139/* **************************************************************** */
140/* */
141/* Functions to manage arrays of strings */
142/* */
143/* **************************************************************** */
144
Jari Aaltocce855b1998-04-17 19:52:44 +0000145#ifdef INCLUDE_UNUSED
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000146/* Find NAME in ARRAY. Return the index of NAME, or -1 if not present.
147 ARRAY should be NULL terminated. */
148int
149find_name_in_array (name, array)
150 char *name, **array;
151{
152 int i;
153
154 for (i = 0; array[i]; i++)
155 if (STREQ (name, array[i]))
156 return (i);
157
158 return (-1);
159}
Jari Aaltocce855b1998-04-17 19:52:44 +0000160#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000161
Jari Aaltobb706242000-03-17 21:46:59 +0000162/* Allocate an array of strings with room for N members. */
163char **
164alloc_array (n)
165 int n;
166{
167 return ((char **)xmalloc ((n) * sizeof (char *)));
168}
169
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000170/* Return the length of ARRAY, a NULL terminated array of char *. */
171int
172array_len (array)
173 char **array;
174{
175 register int i;
176
177 for (i = 0; array[i]; i++);
178 return (i);
179}
180
181/* Free the contents of ARRAY, a NULL terminated array of char *. */
182void
183free_array_members (array)
184 char **array;
185{
186 register int i;
187
188 if (array == 0)
189 return;
190
191 for (i = 0; array[i]; i++)
192 free (array[i]);
193}
194
195void
196free_array (array)
197 char **array;
198{
199 if (array == 0)
200 return;
201
202 free_array_members (array);
203 free (array);
204}
205
206/* Allocate and return a new copy of ARRAY and its contents. */
207char **
208copy_array (array)
209 char **array;
210{
211 register int i;
212 int len;
213 char **new_array;
214
215 len = array_len (array);
216
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;
221
222 return (new_array);
223}
224
225/* Comparison routine for use with qsort() on arrays of strings. Uses
226 strcoll(3) if available, otherwise it uses strcmp(3). */
227int
228qsort_string_compare (s1, s2)
229 register char **s1, **s2;
230{
231#if defined (HAVE_STRCOLL)
232 return (strcoll (*s1, *s2));
233#else /* !HAVE_STRCOLL */
234 int result;
235
236 if ((result = **s1 - **s2) == 0)
237 result = strcmp (*s1, *s2);
238
239 return (result);
240#endif /* !HAVE_STRCOLL */
241}
242
243/* Sort ARRAY, a null terminated array of pointers to strings. */
244void
245sort_char_array (array)
246 char **array;
247{
248 qsort (array, array_len (array), sizeof (char *),
249 (Function *)qsort_string_compare);
250}
251
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. */
259char **
260word_list_to_argv (list, copy, starting_index, ip)
261 WORD_LIST *list;
262 int copy, starting_index, *ip;
263{
264 int count;
265 char **array;
266
267 count = list_length (list);
268 array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
269
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;
275
276 if (ip)
277 *ip = count;
278 return (array);
279}
280
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. */
284WORD_LIST *
285argv_to_word_list (array, copy, starting_index)
286 char **array;
287 int copy, starting_index;
288{
289 WORD_LIST *list;
290 WORD_DESC *w;
291 int i, count;
292
293 if (array == 0 || array[0] == 0)
294 return (WORD_LIST *)NULL;
295
296 for (count = 0; array[count]; count++)
297 ;
298
299 for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
300 {
301 w = make_bare_word (copy ? "" : array[i]);
302 if (copy)
303 {
304 free (w->word);
305 w->word = array[i];
306 }
307 list = make_word_list (w, list);
308 }
309 return (REVERSE_LIST(list, WORD_LIST *));
310}
311
Jari Aaltobb706242000-03-17 21:46:59 +0000312/* 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. */
314int
315find_string_in_alist (string, alist, flags)
316 char *string;
317 STRING_INT_ALIST *alist;
318 int flags;
319{
320 register int i;
321 int r;
322
323 for (i = r = 0; alist[i].word; i++)
324 {
325#if defined (EXTENDED_GLOB)
326 if (flags)
327 r = fnmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
328 else
329#endif
330 r = STREQ (string, alist[i].word);
331
332 if (r)
333 return (alist[i].token);
334 }
335 return -1;
336}
337
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000338/* **************************************************************** */
339/* */
340/* String Management Functions */
341/* */
342/* **************************************************************** */
343
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. */
347char *
348strsub (string, pat, rep, global)
349 char *string, *pat, *rep;
350 int global;
351{
Jari Aaltocce855b1998-04-17 19:52:44 +0000352 int patlen, replen, templen, tempsize, repl, i;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000353 char *temp, *r;
354
355 patlen = strlen (pat);
Jari Aaltocce855b1998-04-17 19:52:44 +0000356 replen = strlen (rep);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000357 for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
358 {
359 if (repl && STREQN (string + i, pat, patlen))
360 {
Jari Aaltocce855b1998-04-17 19:52:44 +0000361 RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000362
363 for (r = rep; *r; )
364 temp[templen++] = *r++;
365
366 i += patlen;
367 repl = global != 0;
368 }
369 else
370 {
371 RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 16);
372 temp[templen++] = string[i++];
373 }
374 }
375 temp[templen] = 0;
376 return (temp);
377}
378
Jari Aaltobb706242000-03-17 21:46:59 +0000379/* 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. */
382char *
383strcreplace (string, c, text, do_glob)
384 char *string;
385 int c;
386 char *text;
387 int do_glob;
388{
389 char *ret, *p, *r, *t;
390 int len, rlen, ind, tlen;
391
392 len = STRLEN (text);
393 rlen = len + strlen (string) + 2;
394 ret = xmalloc (rlen);
395
396 for (p = string, r = ret; p && *p; )
397 {
398 if (*p == c)
399 {
400 if (len)
401 {
402 ind = r - ret;
403 if (do_glob && (glob_pattern_p (text) || strchr (text, '\\')))
404 {
405 t = quote_globbing_chars (text);
406 tlen = strlen (t);
407 RESIZE_MALLOCED_BUFFER (ret, ind, tlen, rlen, rlen);
408 r = ret + ind; /* in case reallocated */
409 strcpy (r, t);
410 r += tlen;
411 free (t);
412 }
413 else
414 {
415 RESIZE_MALLOCED_BUFFER (ret, ind, len, rlen, rlen);
416 r = ret + ind; /* in case reallocated */
417 strcpy (r, text);
418 r += len;
419 }
420 }
421 p++;
422 continue;
423 }
424
425 if (*p == '\\' && p[1] == '&')
426 p++;
427
428 *r++ = *p++;
429 }
430 *r = '\0';
431
432 return ret;
433}
434
Jari Aaltod166f041997-06-05 14:59:13 +0000435#ifdef INCLUDE_UNUSED
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000436/* Remove all leading whitespace from STRING. This includes
437 newlines. STRING should be terminated with a zero. */
438void
439strip_leading (string)
440 char *string;
441{
442 char *start = string;
443
444 while (*string && (whitespace (*string) || *string == '\n'))
445 string++;
446
447 if (string != start)
448 {
449 int len = strlen (string);
450 FASTCOPY (string, start, len);
451 start[len] = '\0';
452 }
453}
Jari Aaltod166f041997-06-05 14:59:13 +0000454#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000455
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. */
459void
Jari Aaltod166f041997-06-05 14:59:13 +0000460strip_trailing (string, len, newlines_only)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000461 char *string;
Jari Aaltod166f041997-06-05 14:59:13 +0000462 int len;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000463 int newlines_only;
464{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000465 while (len >= 0)
466 {
467 if ((newlines_only && string[len] == '\n') ||
468 (!newlines_only && whitespace (string[len])))
469 len--;
470 else
471 break;
472 }
473 string[len + 1] = '\0';
474}
475
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). */
479char *
480strindex (s1, s2)
481 char *s1, *s2;
482{
483 register int i, l, len, c;
484
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))
488 return (s1 + i);
489 return ((char *)NULL);
490}
491
492/* A wrapper for bcopy that can be prototyped in general.h */
493void
494xbcopy (s, d, n)
495 char *s, *d;
496 int n;
497{
498 FASTCOPY (s, d, n);
499}