]>
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 /* 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
)
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');
98 default: *r
++ = '\\'; break;
107 /* **************************************************************** */
109 /* Functions to manage arrays of strings */
111 /* **************************************************************** */
113 /* Find NAME in ARRAY. Return the index of NAME, or -1 if not present.
114 ARRAY should be NULL terminated. */
116 find_name_in_array (name
, array
)
121 for (i
= 0; array
[i
]; i
++)
122 if (STREQ (name
, array
[i
]))
128 /* Return the length of ARRAY, a NULL terminated array of char *. */
135 for (i
= 0; array
[i
]; i
++);
139 /* Free the contents of ARRAY, a NULL terminated array of char *. */
141 free_array_members (array
)
149 for (i
= 0; array
[i
]; i
++)
160 free_array_members (array
);
164 /* Allocate and return a new copy of ARRAY and its contents. */
173 len
= array_len (array
);
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
;
183 /* Comparison routine for use with qsort() on arrays of strings. Uses
184 strcoll(3) if available, otherwise it uses strcmp(3). */
186 qsort_string_compare (s1
, s2
)
187 register char **s1
, **s2
;
189 #if defined (HAVE_STRCOLL)
190 return (strcoll (*s1
, *s2
));
191 #else /* !HAVE_STRCOLL */
194 if ((result
= **s1
- **s2
) == 0)
195 result
= strcmp (*s1
, *s2
);
198 #endif /* !HAVE_STRCOLL */
201 /* Sort ARRAY, a null terminated array of pointers to strings. */
203 sort_char_array (array
)
206 qsort (array
, array_len (array
), sizeof (char *),
207 (Function
*)qsort_string_compare
);
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. */
218 word_list_to_argv (list
, copy
, starting_index
, ip
)
220 int copy
, starting_index
, *ip
;
225 count
= list_length (list
);
226 array
= (char **)xmalloc ((1 + count
+ starting_index
) * sizeof (char *));
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
;
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. */
243 argv_to_word_list (array
, copy
, starting_index
)
245 int copy
, starting_index
;
251 if (array
== 0 || array
[0] == 0)
252 return (WORD_LIST
*)NULL
;
254 for (count
= 0; array
[count
]; count
++)
257 for (i
= starting_index
, list
= (WORD_LIST
*)NULL
; i
< count
; i
++)
259 w
= make_bare_word (copy
? "" : array
[i
]);
265 list
= make_word_list (w
, list
);
267 return (REVERSE_LIST(list
, WORD_LIST
*));
270 /* **************************************************************** */
272 /* String Management Functions */
274 /* **************************************************************** */
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. */
280 strsub (string
, pat
, rep
, global
)
281 char *string
, *pat
, *rep
;
284 int patlen
, templen
, tempsize
, repl
, i
;
287 patlen
= strlen (pat
);
288 for (temp
= (char *)NULL
, i
= templen
= tempsize
= 0, repl
= 1; string
[i
]; )
290 if (repl
&& STREQN (string
+ i
, pat
, patlen
))
292 RESIZE_MALLOCED_BUFFER (temp
, templen
, patlen
, tempsize
, (patlen
* 2));
295 temp
[templen
++] = *r
++;
302 RESIZE_MALLOCED_BUFFER (temp
, templen
, 1, tempsize
, 16);
303 temp
[templen
++] = string
[i
++];
310 /* Remove all leading whitespace from STRING. This includes
311 newlines. STRING should be terminated with a zero. */
313 strip_leading (string
)
316 char *start
= string
;
318 while (*string
&& (whitespace (*string
) || *string
== '\n'))
323 int len
= strlen (string
);
324 FASTCOPY (string
, start
, len
);
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. */
333 strip_trailing (string
, newlines_only
)
337 int len
= strlen (string
) - 1;
341 if ((newlines_only
&& string
[len
] == '\n') ||
342 (!newlines_only
&& whitespace (string
[len
])))
347 string
[len
+ 1] = '\0';
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). */
357 register int i
, l
, len
, c
;
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))
363 return ((char *)NULL
);
366 /* A wrapper for bcopy that can be prototyped in general.h */