]>
git.ipfire.org Git - thirdparty/bash.git/blob - lib/sh/strtrans.c
1 /* strtrans.c - Translate and untranslate strings with ANSI-C escape
5 Free Software Foundation, Inc.
7 This file is part of GNU Bash, the Bourne Again SHell.
9 Bash is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
14 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License along
20 with Bash; see the file COPYING. If not, write to the Free Software
21 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
25 #if defined (HAVE_UNISTD_H)
31 #include <chartypes.h>
38 #define ESC '\033' /* ASCII */
40 /* Convert STRING by expanding the escape sequences specified by the
41 ANSI C standard. If SAWC is non-null, recognize `\c' and use that
42 as a string terminator. If we see \c, set *SAWC to 1 before
43 returning. LEN is the length of STRING. If (FLAGS&1) is non-zero,
44 that we're translating a string for `echo -e', and therefore should not
45 treat a single quote as a character that may be escaped with a backslash.
46 If (FLAGS&2) is non-zero, we're expanding for the parser and want to
47 quote CTLESC and CTLNUL with CTLESC. If (flags&4) is non-zero, we want
48 to remove the backslash before any unrecognized escape sequence. */
50 ansicstr (string
, len
, flags
, sawc
, rlen
)
52 int len
, flags
, *sawc
, *rlen
;
57 if (string
== 0 || *string
== '\0')
58 return ((char *)NULL
);
60 ret
= (char *)xmalloc (2*len
+ 1); /* 2*len for possible CTLESC */
61 for (r
= ret
, s
= string
; s
&& *s
; )
64 if (c
!= '\\' || *s
== '\0')
70 #if defined (__STDC__)
71 case 'a': c
= '\a'; break;
72 case 'v': c
= '\v'; break;
74 case 'a': c
= '\007'; break;
75 case 'v': c
= (int) 0x0B; break;
77 case 'b': c
= '\b'; break;
78 case 'e': case 'E': /* ESC -- non-ANSI */
80 case 'f': c
= '\f'; break;
81 case 'n': c
= '\n'; break;
82 case 'r': c
= '\r'; break;
83 case 't': c
= '\t'; break;
84 case '1': case '2': case '3':
85 case '4': case '5': case '6':
96 /* If (FLAGS & 1), we're translating a string for echo -e (or
97 the equivalent xpg_echo option), so we obey the SUSv3/
98 POSIX-2001 requirement and accept 0-3 octal digits after
100 temp
= 2 + ((flags
& 1) && (c
== '0'));
101 for (c
-= '0'; ISOCTAL (*s
) && temp
--; s
++)
102 c
= (c
* 8) + OCTVALUE (*s
);
105 case 'x': /* Hex digit -- non-ANSI */
106 if ((flags
& 2) && *s
== '{')
108 flags
|= 16; /* internal flag value */
111 /* Consume at least two hex characters */
112 for (temp
= 2, c
= 0; ISXDIGIT ((unsigned char)*s
) && temp
--; s
++)
113 c
= (c
* 16) + HEXVALUE (*s
);
114 /* DGK says that after a `\x{' ksh93 consumes ISXDIGIT chars
115 until a non-xdigit or `}', so potentially more than two
116 chars are consumed. */
119 for ( ; ISXDIGIT ((unsigned char)*s
); s
++)
120 c
= (c
* 16) + HEXVALUE (*s
);
125 /* \x followed by non-hex digits is passed through unchanged */
135 case '\'': case '"': case '?':
148 else if ((flags
& 1) == 0 && (c
= *s
))
156 if ((flags
& 4) == 0)
160 if ((flags
& 2) && (c
== CTLESC
|| c
== CTLNUL
))
171 /* Take a string STR, possibly containing non-printing characters, and turn it
172 into a $'...' ANSI-C style quoted string. Returns a new string. */
174 ansic_quote (str
, flags
, rlen
)
182 if (str
== 0 || *str
== 0)
187 r
= ret
= (char *)xmalloc (rsize
);
192 for (s
= str
, l
= 0; *s
; s
++)
195 l
= 1; /* 1 == add backslash; 0 == no backslash */
198 case ESC
: c
= 'E'; break;
200 case '\a': c
= 'a'; break;
201 case '\v': c
= 'v'; break;
203 case '\007': c
= 'a'; break;
204 case 0x0b: c
= 'v'; break;
207 case '\b': c
= 'b'; break;
208 case '\f': c
= 'f'; break;
209 case '\n': c
= 'n'; break;
210 case '\r': c
= 'r'; break;
211 case '\t': c
= 't'; break;
216 if (ISPRINT (c
) == 0)
219 *r
++ = TOCHAR ((c
>> 6) & 07);
220 *r
++ = TOCHAR ((c
>> 3) & 07);
221 *r
++ = TOCHAR (c
& 07);
239 /* return 1 if we need to quote with $'...' because of non-printing chars. */
241 ansic_shouldquote (string
)
250 for (s
= string
; c
= *s
; s
++)
251 if (ISPRINT (c
) == 0)
257 /* $'...' ANSI-C expand the portion of STRING between START and END and
258 return the result. The result cannot be longer than the input string. */
260 ansiexpand (string
, start
, end
, lenp
)
262 int start
, end
, *lenp
;
267 temp
= (char *)xmalloc (end
- start
+ 1);
268 for (tlen
= 0, len
= start
; len
< end
; )
269 temp
[tlen
++] = string
[len
++];
274 t
= ansicstr (temp
, tlen
, 2, (int *)NULL
, lenp
);