| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* stringlib.c - Miscellaneous string functions. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Copyright (C) 1996-2009 Free Software Foundation, Inc.
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Bash is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |    it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |    the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |    (at your option) any later version. | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Bash is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |    GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "bashtypes.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "bashansi.h"
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include "chartypes.h"
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "shell.h"
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "pathexp.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include <glob/glob.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (EXTENDED_GLOB)
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #  include <glob/strmatch.h>
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		Functions to manage arrays of strings		    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Find STRING in ALIST, a list of string key/int value pairs.  If FLAGS
 | 
					
						
							|  |  |  |    is 1, STRING is treated as a pattern and matched using strmatch. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | find_string_in_alist (string, alist, flags) | 
					
						
							|  |  |  |      char *string; | 
					
						
							|  |  |  |      STRING_INT_ALIST *alist; | 
					
						
							|  |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register int i; | 
					
						
							|  |  |  |   int r; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   for (i = r = 0; alist[i].word; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #if defined (EXTENDED_GLOB)
 | 
					
						
							|  |  |  |       if (flags) | 
					
						
							|  |  |  | 	r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	r = STREQ (string, alist[i].word); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (r) | 
					
						
							|  |  |  | 	return (alist[i].token); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return -1; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Find TOKEN in ALIST, a list of string/int value pairs.  Return the
 | 
					
						
							|  |  |  |    corresponding string.  Allocates memory for the returned | 
					
						
							|  |  |  |    string.  FLAGS is currently ignored, but reserved. */ | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | find_token_in_alist (token, alist, flags) | 
					
						
							|  |  |  |      int token; | 
					
						
							|  |  |  |      STRING_INT_ALIST *alist; | 
					
						
							|  |  |  |      int flags; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register int i; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   for (i = 0; alist[i].word; i++) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (alist[i].token == token) | 
					
						
							|  |  |  |         return (savestring (alist[i].word)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return ((char *)NULL); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | find_index_in_alist (string, alist, flags) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |      char *string; | 
					
						
							|  |  |  |      STRING_INT_ALIST *alist; | 
					
						
							|  |  |  |      int flags; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  |   int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = r = 0; alist[i].word; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #if defined (EXTENDED_GLOB)
 | 
					
						
							|  |  |  |       if (flags) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	r = STREQ (string, alist[i].word); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (r) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	return (i); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*		    String Management Functions			    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Cons a new string from STRING starting at START and ending at END,
 | 
					
						
							|  |  |  |    not including END. */ | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | substring (string, start, end) | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |      const char *string; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      int start, end; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int len; | 
					
						
							|  |  |  |   register char *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   len = end - start; | 
					
						
							|  |  |  |   result = (char *)xmalloc (len + 1); | 
					
						
							|  |  |  |   strncpy (result, string + start, len); | 
					
						
							|  |  |  |   result[len] = '\0'; | 
					
						
							|  |  |  |   return (result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Replace occurrences of PAT with REP in STRING.  If GLOBAL is non-zero,
 | 
					
						
							|  |  |  |    replace all occurrences, otherwise replace only the first. | 
					
						
							|  |  |  |    This returns a new string; the caller should free it. */ | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | strsub (string, pat, rep, global) | 
					
						
							|  |  |  |      char *string, *pat, *rep; | 
					
						
							|  |  |  |      int global; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   int patlen, replen, templen, tempsize, repl, i; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   char *temp, *r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   patlen = strlen (pat); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   replen = strlen (rep); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (repl && STREQN (string + i, pat, patlen)) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  if (replen) | 
					
						
							|  |  |  | 	    RESIZE_MALLOCED_BUFFER (temp, templen, replen, tempsize, (replen * 2)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  for (r = rep; *r; ) | 
					
						
							|  |  |  | 	    temp[templen++] = *r++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  i += patlen ? patlen : 1;	/* avoid infinite recursion */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  repl = global != 0; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 16); | 
					
						
							|  |  |  | 	  temp[templen++] = string[i++]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   if (temp) | 
					
						
							|  |  |  |     temp[templen] = 0; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     temp = savestring (string); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (temp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | /* Replace all instances of C in STRING with TEXT.  TEXT may be empty or
 | 
					
						
							|  |  |  |    NULL.  If DO_GLOB is non-zero, we quote the replacement text for | 
					
						
							|  |  |  |    globbing.  Backslash may be used to quote C. */ | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | strcreplace (string, c, text, do_glob) | 
					
						
							|  |  |  |      char *string; | 
					
						
							|  |  |  |      int c; | 
					
						
							|  |  |  |      char *text; | 
					
						
							|  |  |  |      int do_glob; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *ret, *p, *r, *t; | 
					
						
							|  |  |  |   int len, rlen, ind, tlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   len = STRLEN (text); | 
					
						
							|  |  |  |   rlen = len + strlen (string) + 2; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   ret = (char *)xmalloc (rlen); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (p = string, r = ret; p && *p; ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (*p == c) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (len) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      ind = r - ret; | 
					
						
							|  |  |  | 	      if (do_glob && (glob_pattern_p (text) || strchr (text, '\\'))) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  t = quote_globbing_chars (text); | 
					
						
							|  |  |  | 		  tlen = strlen (t); | 
					
						
							|  |  |  | 		  RESIZE_MALLOCED_BUFFER (ret, ind, tlen, rlen, rlen); | 
					
						
							|  |  |  | 		  r = ret + ind;	/* in case reallocated */ | 
					
						
							|  |  |  | 		  strcpy (r, t); | 
					
						
							|  |  |  | 		  r += tlen; | 
					
						
							|  |  |  | 		  free (t); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  RESIZE_MALLOCED_BUFFER (ret, ind, len, rlen, rlen); | 
					
						
							|  |  |  | 		  r = ret + ind;	/* in case reallocated */ | 
					
						
							|  |  |  | 		  strcpy (r, text); | 
					
						
							|  |  |  | 		  r += len; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  p++; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       if (*p == '\\' && p[1] == c) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	p++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       ind = r - ret; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       RESIZE_MALLOCED_BUFFER (ret, ind, 2, rlen, rlen); | 
					
						
							|  |  |  |       r = ret + ind;			/* in case reallocated */ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       *r++ = *p++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   *r = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #ifdef INCLUDE_UNUSED
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Remove all leading whitespace from STRING.  This includes
 | 
					
						
							|  |  |  |    newlines.  STRING should be terminated with a zero. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | strip_leading (string) | 
					
						
							|  |  |  |      char *string; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *start = string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (*string && (whitespace (*string) || *string == '\n')) | 
					
						
							|  |  |  |     string++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (string != start) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       int len = strlen (string); | 
					
						
							|  |  |  |       FASTCOPY (string, start, len); | 
					
						
							|  |  |  |       start[len] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Remove all trailing whitespace from STRING.  This includes
 | 
					
						
							|  |  |  |    newlines.  If NEWLINES_ONLY is non-zero, only trailing newlines | 
					
						
							|  |  |  |    are removed.  STRING should be terminated with a zero. */ | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | strip_trailing (string, len, newlines_only) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      char *string; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |      int len; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      int newlines_only; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   while (len >= 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if ((newlines_only && string[len] == '\n') || | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  (!newlines_only && whitespace (string[len]))) | 
					
						
							|  |  |  | 	len--; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	break; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   string[len + 1] = '\0'; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* A wrapper for bcopy that can be prototyped in general.h */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | xbcopy (s, d, n) | 
					
						
							|  |  |  |      char *s, *d; | 
					
						
							|  |  |  |      int n; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   FASTCOPY (s, d, n); | 
					
						
							|  |  |  | } |