| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* strtrans.c - Translate and untranslate strings with ANSI-C escape sequences. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /* Copyright (C) 2000-2011 Free Software Foundation, Inc.
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +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. | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +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. | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +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/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <config.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include <bashansi.h>
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include <chartypes.h>
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "shell.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #include "shmbchar.h"
 | 
					
						
							|  |  |  | #include "shmbutil.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | #ifdef ESC
 | 
					
						
							|  |  |  | #undef ESC
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #define ESC '\033'	/* ASCII */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Convert STRING by expanding the escape sequences specified by the
 | 
					
						
							|  |  |  |    ANSI C standard.  If SAWC is non-null, recognize `\c' and use that | 
					
						
							|  |  |  |    as a string terminator.  If we see \c, set *SAWC to 1 before | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    returning.  LEN is the length of STRING.  If (FLAGS&1) is non-zero, | 
					
						
							|  |  |  |    that we're translating a string for `echo -e', and therefore should not | 
					
						
							|  |  |  |    treat a single quote as a character that may be escaped with a backslash. | 
					
						
							|  |  |  |    If (FLAGS&2) is non-zero, we're expanding for the parser and want to | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |    quote CTLESC and CTLNUL with CTLESC.  If (flags&4) is non-zero, we want | 
					
						
							|  |  |  |    to remove the backslash before any unrecognized escape sequence. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | char * | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | ansicstr (string, len, flags, sawc, rlen) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |      char *string; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      int len, flags, *sawc, *rlen; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   int c, temp; | 
					
						
							|  |  |  |   char *ret, *r, *s; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   unsigned long v; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (string == 0 || *string == '\0') | 
					
						
							|  |  |  |     return ((char *)NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |   ret = (char *)xmalloc (4*len + 1); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   ret = (char *)xmalloc (2*len + 1);	/* 2*len for possible CTLESC */ | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   for (r = ret, s = string; s && *s; ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       c = *s++; | 
					
						
							|  |  |  |       if (c != '\\' || *s == '\0') | 
					
						
							|  |  |  | 	*r++ = c; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  switch (c = *s++) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | #if defined (__STDC__)
 | 
					
						
							|  |  |  | 	    case 'a': c = '\a'; break; | 
					
						
							|  |  |  | 	    case 'v': c = '\v'; break; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	    case 'a': c = (int) 0x07; break; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	    case 'v': c = (int) 0x0B; break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	    case 'b': c = '\b'; break; | 
					
						
							|  |  |  | 	    case 'e': case 'E':		/* ESC -- non-ANSI */ | 
					
						
							|  |  |  | 	      c = ESC; break; | 
					
						
							|  |  |  | 	    case 'f': c = '\f'; break; | 
					
						
							|  |  |  | 	    case 'n': c = '\n'; break; | 
					
						
							|  |  |  | 	    case 'r': c = '\r'; break; | 
					
						
							|  |  |  | 	    case 't': c = '\t'; break; | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 	    case '1': case '2': case '3': | 
					
						
							|  |  |  | 	    case '4': case '5': case '6': | 
					
						
							|  |  |  | 	    case '7': | 
					
						
							|  |  |  | #if 1
 | 
					
						
							|  |  |  | 	      if (flags & 1) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  *r++ = '\\'; | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	    /*FALLTHROUGH*/ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	    case '0': | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      /* If (FLAGS & 1), we're translating a string for echo -e (or
 | 
					
						
							|  |  |  | 		 the equivalent xpg_echo option), so we obey the SUSv3/ | 
					
						
							|  |  |  | 		 POSIX-2001 requirement and accept 0-3 octal digits after | 
					
						
							|  |  |  | 		 a leading `0'. */ | 
					
						
							|  |  |  | 	      temp = 2 + ((flags & 1) && (c == '0')); | 
					
						
							|  |  |  | 	      for (c -= '0'; ISOCTAL (*s) && temp--; s++) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 		c = (c * 8) + OCTVALUE (*s); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	      c &= 0xFF; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	      break; | 
					
						
							|  |  |  | 	    case 'x':			/* Hex digit -- non-ANSI */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      if ((flags & 2) && *s == '{') | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  flags |= 16;		/* internal flag value */ | 
					
						
							|  |  |  | 		  s++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      /* Consume at least two hex characters */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	      for (temp = 2, c = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 		c = (c * 16) + HEXVALUE (*s); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      /* DGK says that after a `\x{' ksh93 consumes ISXDIGIT chars
 | 
					
						
							|  |  |  | 		 until a non-xdigit or `}', so potentially more than two | 
					
						
							|  |  |  | 		 chars are consumed. */ | 
					
						
							|  |  |  | 	      if (flags & 16) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  for ( ; ISXDIGIT ((unsigned char)*s); s++) | 
					
						
							|  |  |  | 		    c = (c * 16) + HEXVALUE (*s); | 
					
						
							|  |  |  | 		  flags &= ~16; | 
					
						
							|  |  |  | 		  if (*s == '}') | 
					
						
							|  |  |  | 		    s++; | 
					
						
							|  |  |  | 	        } | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	      /* \x followed by non-hex digits is passed through unchanged */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      else if (temp == 2) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 		  *r++ = '\\'; | 
					
						
							|  |  |  | 		  c = 'x'; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	      c &= 0xFF; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	      break; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  | 	    case 'u': | 
					
						
							|  |  |  | 	    case 'U': | 
					
						
							|  |  |  | 	      temp = (c == 'u') ? 4 : 8;	/* \uNNNN \UNNNNNNNN */ | 
					
						
							|  |  |  | 	      for (v = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++) | 
					
						
							|  |  |  | 		v = (v * 16) + HEXVALUE (*s); | 
					
						
							|  |  |  | 	      if (temp == ((c == 'u') ? 4 : 8)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  *r++ = '\\';	/* c remains unchanged */ | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	      else if (v <= 0x7f)	/* <= 0x7f translates directly */ | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 		  c = v; | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  temp = u32cconv (v, r); | 
					
						
							|  |  |  | 		  r += temp; | 
					
						
							|  |  |  | 		  continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	    case '\\': | 
					
						
							|  |  |  | 	      break; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	    case '\'': case '"': case '?': | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      if (flags & 1) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 		*r++ = '\\'; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    case 'c': | 
					
						
							|  |  |  | 	      if (sawc) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  *sawc = 1; | 
					
						
							|  |  |  | 		  *r = '\0'; | 
					
						
							|  |  |  | 		  if (rlen) | 
					
						
							|  |  |  | 		    *rlen = r - ret; | 
					
						
							|  |  |  | 		  return ret; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	      else if ((flags & 1) == 0 && *s == 0) | 
					
						
							|  |  |  | 		;		/* pass \c through */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      else if ((flags & 1) == 0 && (c = *s)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  s++; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 		  if ((flags & 2) && c == '\\' && c == *s) | 
					
						
							|  |  |  | 		    s++;	/* Posix requires $'\c\\' do backslash escaping */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 		  c = TOCTRL(c); | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/*FALLTHROUGH*/ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	    default: | 
					
						
							|  |  |  | 		if ((flags & 4) == 0) | 
					
						
							|  |  |  | 		  *r++ = '\\'; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  if ((flags & 2) && (c == CTLESC || c == CTLNUL)) | 
					
						
							|  |  |  | 	    *r++ = CTLESC; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  *r++ = c; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   *r = '\0'; | 
					
						
							|  |  |  |   if (rlen) | 
					
						
							|  |  |  |     *rlen = r - ret; | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Take a string STR, possibly containing non-printing characters, and turn it
 | 
					
						
							|  |  |  |    into a $'...' ANSI-C style quoted string.  Returns a new string. */ | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | ansic_quote (str, flags, rlen) | 
					
						
							|  |  |  |      char *str; | 
					
						
							|  |  |  |      int flags, *rlen; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   char *r, *ret, *s; | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   int l, rsize; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   unsigned char c; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   size_t clen; | 
					
						
							|  |  |  |   int b; | 
					
						
							|  |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |   wchar_t wc; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (str == 0 || *str == 0) | 
					
						
							|  |  |  |     return ((char *)0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   l = strlen (str); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   rsize = 4 * l + 4; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   r = ret = (char *)xmalloc (rsize); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   *r++ = '$'; | 
					
						
							|  |  |  |   *r++ = '\''; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   s = str; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (s = str; c = *s; s++) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       b = l = 1;		/* 1 == add backslash; 0 == no backslash */ | 
					
						
							|  |  |  |       clen = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       switch (c) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case ESC: c = 'E'; break; | 
					
						
							|  |  |  | #ifdef __STDC__
 | 
					
						
							|  |  |  | 	case '\a': c = 'a'; break; | 
					
						
							|  |  |  | 	case '\v': c = 'v'; break; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	case 0x07: c = 'a'; break; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	case 0x0b: c = 'v'; break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case '\b': c = 'b'; break; | 
					
						
							|  |  |  | 	case '\f': c = 'f'; break; | 
					
						
							|  |  |  | 	case '\n': c = 'n'; break; | 
					
						
							|  |  |  | 	case '\r': c = 'r'; break; | 
					
						
							|  |  |  | 	case '\t': c = 't'; break; | 
					
						
							|  |  |  | 	case '\\': | 
					
						
							|  |  |  | 	case '\'': | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  | 	  b = is_basic (c); | 
					
						
							|  |  |  | 	  /* XXX - clen comparison to 0 is dicey */ | 
					
						
							|  |  |  | 	  if ((b == 0 && ((clen = mbrtowc (&wc, s, MB_CUR_MAX, 0)) < 0 || MB_INVALIDCH (clen) || iswprint (wc) == 0)) || | 
					
						
							|  |  |  | 	      (b == 1 && ISPRINT (c) == 0)) | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  if (ISPRINT (c) == 0) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      *r++ = '\\'; | 
					
						
							|  |  |  | 	      *r++ = TOCHAR ((c >> 6) & 07); | 
					
						
							|  |  |  | 	      *r++ = TOCHAR ((c >> 3) & 07); | 
					
						
							|  |  |  | 	      *r++ = TOCHAR (c & 07); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  l = 0; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (b == 0 && clen == 0) | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       if (l) | 
					
						
							|  |  |  | 	*r++ = '\\'; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (clen == 1) | 
					
						
							|  |  |  | 	*r++ = c; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  for (b = 0; b < (int)clen; b++) | 
					
						
							|  |  |  | 	    *r++ = (unsigned char)s[b]; | 
					
						
							|  |  |  | 	  s += clen - 1;	/* -1 because of the increment above */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *r++ = '\''; | 
					
						
							|  |  |  |   *r = '\0'; | 
					
						
							|  |  |  |   if (rlen) | 
					
						
							|  |  |  |     *rlen = r - ret; | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | ansic_wshouldquote (string) | 
					
						
							|  |  |  |      const char *string; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const wchar_t *wcs; | 
					
						
							|  |  |  |   wchar_t wcc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   wchar_t *wcstr = NULL; | 
					
						
							|  |  |  |   size_t slen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   slen = mbstowcs (wcstr, string, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (slen == -1) | 
					
						
							|  |  |  |     slen = 0; | 
					
						
							|  |  |  |   wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1)); | 
					
						
							|  |  |  |   mbstowcs (wcstr, string, slen + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (wcs = wcstr; wcc = *wcs; wcs++) | 
					
						
							|  |  |  |     if (iswprint(wcc) == 0) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  | 	free (wcstr); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   free (wcstr); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | /* return 1 if we need to quote with $'...' because of non-printing chars. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | ansic_shouldquote (string) | 
					
						
							|  |  |  |      const char *string; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const char *s; | 
					
						
							|  |  |  |   unsigned char c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (string == 0) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (s = string; c = *s; s++) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |     { | 
					
						
							|  |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |       if (is_basic (c) == 0) | 
					
						
							|  |  |  | 	return (ansic_wshouldquote (s)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |       if (ISPRINT (c) == 0) | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* $'...' ANSI-C expand the portion of STRING between START and END and
 | 
					
						
							|  |  |  |    return the result.  The result cannot be longer than the input string. */ | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | ansiexpand (string, start, end, lenp) | 
					
						
							|  |  |  |      char *string; | 
					
						
							|  |  |  |      int start, end, *lenp; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *temp, *t; | 
					
						
							|  |  |  |   int len, tlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   temp = (char *)xmalloc (end - start + 1); | 
					
						
							|  |  |  |   for (tlen = 0, len = start; len < end; ) | 
					
						
							|  |  |  |     temp[tlen++] = string[len++]; | 
					
						
							|  |  |  |   temp[tlen] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (*temp) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       t = ansicstr (temp, tlen, 2, (int *)NULL, lenp); | 
					
						
							|  |  |  |       free (temp); | 
					
						
							|  |  |  |       return (t); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (lenp) | 
					
						
							|  |  |  | 	*lenp = 0; | 
					
						
							|  |  |  |       return (temp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |