]>
git.ipfire.org Git - thirdparty/bash.git/blob - stringlib.c
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 #define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
42 #define OCTVALUE(c) ((c) - '0')
45 # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
49 ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
51 /* Convert STRING by expanding the escape sequences specified by the
52 ANSI C standard. If SAWC is non-null, recognize `\c' and use that
53 as a string terminator. If we see \c, set *SAWC to 1 before
54 returning. LEN is the length of STRING. */
56 ansicstr (string
, len
, sawc
, rlen
)
58 int len
, *sawc
, *rlen
;
63 if (string
== 0 || *string
== '\0')
64 return ((char *)NULL
);
66 ret
= xmalloc (len
+ 1);
67 for (r
= ret
, s
= string
; s
&& *s
; )
70 if (c
!= '\\' || *s
== '\0')
76 #if defined (__STDC__)
77 case 'a': c
= '\a'; break;
78 case 'v': c
= '\v'; break;
80 case 'a': c
= '\007'; break;
81 case 'v': c
= (int) 0x0B; break;
83 case 'b': c
= '\b'; break;
84 case 'e': case 'E': /* ESC -- non-ANSI */
86 case 'f': c
= '\f'; break;
87 case 'n': c
= '\n'; break;
88 case 'r': c
= '\r'; break;
89 case 't': c
= '\t'; break;
90 case '0': case '1': case '2': case '3':
91 case '4': case '5': case '6': case '7':
92 for (temp
= 2, c
-= '0'; ISOCTAL (*s
) && temp
--; s
++)
93 c
= (c
* 8) + OCTVALUE (*s
);
95 case 'x': /* Hex digit -- non-ANSI */
96 for (temp
= 3, c
= 0; isxdigit (*s
) && temp
--; s
++)
97 c
= (c
* 16) + HEXVALUE (*s
);
98 /* \x followed by non-hex digits is passed through unchanged */
117 default: *r
++ = '\\'; break;
128 /* **************************************************************** */
130 /* Functions to manage arrays of strings */
132 /* **************************************************************** */
134 #ifdef INCLUDE_UNUSED
135 /* Find NAME in ARRAY. Return the index of NAME, or -1 if not present.
136 ARRAY should be NULL terminated. */
138 find_name_in_array (name
, array
)
143 for (i
= 0; array
[i
]; i
++)
144 if (STREQ (name
, array
[i
]))
151 /* Return the length of ARRAY, a NULL terminated array of char *. */
158 for (i
= 0; array
[i
]; i
++);
162 /* Free the contents of ARRAY, a NULL terminated array of char *. */
164 free_array_members (array
)
172 for (i
= 0; array
[i
]; i
++)
183 free_array_members (array
);
187 /* Allocate and return a new copy of ARRAY and its contents. */
196 len
= array_len (array
);
198 new_array
= (char **)xmalloc ((len
+ 1) * sizeof (char *));
199 for (i
= 0; array
[i
]; i
++)
200 new_array
[i
] = savestring (array
[i
]);
201 new_array
[i
] = (char *)NULL
;
206 /* Comparison routine for use with qsort() on arrays of strings. Uses
207 strcoll(3) if available, otherwise it uses strcmp(3). */
209 qsort_string_compare (s1
, s2
)
210 register char **s1
, **s2
;
212 #if defined (HAVE_STRCOLL)
213 return (strcoll (*s1
, *s2
));
214 #else /* !HAVE_STRCOLL */
217 if ((result
= **s1
- **s2
) == 0)
218 result
= strcmp (*s1
, *s2
);
221 #endif /* !HAVE_STRCOLL */
224 /* Sort ARRAY, a null terminated array of pointers to strings. */
226 sort_char_array (array
)
229 qsort (array
, array_len (array
), sizeof (char *),
230 (Function
*)qsort_string_compare
);
233 /* Cons up a new array of words. The words are taken from LIST,
234 which is a WORD_LIST *. If COPY is true, everything is malloc'ed,
235 so you should free everything in this array when you are done.
236 The array is NULL terminated. If IP is non-null, it gets the
237 number of words in the returned array. STARTING_INDEX says where
238 to start filling in the returned array; it can be used to reserve
239 space at the beginning of the array. */
241 word_list_to_argv (list
, copy
, starting_index
, ip
)
243 int copy
, starting_index
, *ip
;
248 count
= list_length (list
);
249 array
= (char **)xmalloc ((1 + count
+ starting_index
) * sizeof (char *));
251 for (count
= 0; count
< starting_index
; count
++)
252 array
[count
] = (char *)NULL
;
253 for (count
= starting_index
; list
; count
++, list
= list
->next
)
254 array
[count
] = copy
? savestring (list
->word
->word
) : list
->word
->word
;
255 array
[count
] = (char *)NULL
;
262 /* Convert an array of strings into the form used internally by the shell.
263 COPY means to copy the values in ARRAY into the returned list rather
264 than allocate new storage. STARTING_INDEX says where in ARRAY to begin. */
266 argv_to_word_list (array
, copy
, starting_index
)
268 int copy
, starting_index
;
274 if (array
== 0 || array
[0] == 0)
275 return (WORD_LIST
*)NULL
;
277 for (count
= 0; array
[count
]; count
++)
280 for (i
= starting_index
, list
= (WORD_LIST
*)NULL
; i
< count
; i
++)
282 w
= make_bare_word (copy
? "" : array
[i
]);
288 list
= make_word_list (w
, list
);
290 return (REVERSE_LIST(list
, WORD_LIST
*));
293 /* **************************************************************** */
295 /* String Management Functions */
297 /* **************************************************************** */
299 /* Replace occurrences of PAT with REP in STRING. If GLOBAL is non-zero,
300 replace all occurrences, otherwise replace only the first.
301 This returns a new string; the caller should free it. */
303 strsub (string
, pat
, rep
, global
)
304 char *string
, *pat
, *rep
;
307 int patlen
, replen
, templen
, tempsize
, repl
, i
;
310 patlen
= strlen (pat
);
311 replen
= strlen (rep
);
312 for (temp
= (char *)NULL
, i
= templen
= tempsize
= 0, repl
= 1; string
[i
]; )
314 if (repl
&& STREQN (string
+ i
, pat
, patlen
))
316 RESIZE_MALLOCED_BUFFER (temp
, templen
, replen
, tempsize
, (replen
* 2));
319 temp
[templen
++] = *r
++;
326 RESIZE_MALLOCED_BUFFER (temp
, templen
, 1, tempsize
, 16);
327 temp
[templen
++] = string
[i
++];
334 #ifdef INCLUDE_UNUSED
335 /* Remove all leading whitespace from STRING. This includes
336 newlines. STRING should be terminated with a zero. */
338 strip_leading (string
)
341 char *start
= string
;
343 while (*string
&& (whitespace (*string
) || *string
== '\n'))
348 int len
= strlen (string
);
349 FASTCOPY (string
, start
, len
);
355 /* Remove all trailing whitespace from STRING. This includes
356 newlines. If NEWLINES_ONLY is non-zero, only trailing newlines
357 are removed. STRING should be terminated with a zero. */
359 strip_trailing (string
, len
, newlines_only
)
366 if ((newlines_only
&& string
[len
] == '\n') ||
367 (!newlines_only
&& whitespace (string
[len
])))
372 string
[len
+ 1] = '\0';
375 /* Determine if s2 occurs in s1. If so, return a pointer to the
376 match in s1. The compare is case insensitive. This is a
377 case-insensitive strstr(3). */
382 register int i
, l
, len
, c
;
384 c
= to_upper (s2
[0]);
385 for (i
= 0, len
= strlen (s1
), l
= strlen (s2
); (len
- i
) >= l
; i
++)
386 if ((to_upper (s1
[i
]) == c
) && (strncasecmp (s1
+ i
, s2
, l
) == 0))
388 return ((char *)NULL
);
391 /* A wrapper for bcopy that can be prototyped in general.h */