206 lines
4.8 KiB
C
206 lines
4.8 KiB
C
|
|
/* strtrans.c - Translate and untranslate strings with ANSI-C escape
|
||
|
|
sequences. */
|
||
|
|
|
||
|
|
/* Copyright (C) 2000
|
||
|
|
Free Software Foundation, Inc.
|
||
|
|
|
||
|
|
This file is part of GNU Bash, the Bourne Again SHell.
|
||
|
|
|
||
|
|
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 2, or (at your option) any later
|
||
|
|
version.
|
||
|
|
|
||
|
|
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.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU General Public License along
|
||
|
|
with Bash; see the file COPYING. If not, write to the Free Software
|
||
|
|
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||
|
|
|
||
|
|
#include <config.h>
|
||
|
|
|
||
|
|
#if defined (HAVE_UNISTD_H)
|
||
|
|
# include <unistd.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#include "bashansi.h"
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <ctype.h>
|
||
|
|
|
||
|
|
#include "shell.h"
|
||
|
|
|
||
|
|
#ifdef ESC
|
||
|
|
#undef ESC
|
||
|
|
#endif
|
||
|
|
#define ESC '\033' /* ASCII */
|
||
|
|
|
||
|
|
#ifndef ISOCTAL
|
||
|
|
#define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifndef OCTVALUE
|
||
|
|
#define OCTVALUE(c) ((c) - '0')
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifndef isxdigit
|
||
|
|
# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define HEXVALUE(c) \
|
||
|
|
((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0')
|
||
|
|
|
||
|
|
/* 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
|
||
|
|
returning. LEN is the length of STRING. FOR_ECHO is a flag that
|
||
|
|
means, if 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. */
|
||
|
|
char *
|
||
|
|
ansicstr (string, len, for_echo, sawc, rlen)
|
||
|
|
char *string;
|
||
|
|
int len, for_echo, *sawc, *rlen;
|
||
|
|
{
|
||
|
|
int c, temp;
|
||
|
|
char *ret, *r, *s;
|
||
|
|
|
||
|
|
if (string == 0 || *string == '\0')
|
||
|
|
return ((char *)NULL);
|
||
|
|
|
||
|
|
ret = xmalloc (len + 1);
|
||
|
|
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
|
||
|
|
case 'a': c = '\007'; break;
|
||
|
|
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;
|
||
|
|
case '0': case '1': case '2': case '3':
|
||
|
|
case '4': case '5': case '6': case '7':
|
||
|
|
for (temp = 2, c -= '0'; ISOCTAL (*s) && temp--; s++)
|
||
|
|
c = (c * 8) + OCTVALUE (*s);
|
||
|
|
break;
|
||
|
|
case 'x': /* Hex digit -- non-ANSI */
|
||
|
|
for (temp = 3, c = 0; isxdigit (*s) && temp--; s++)
|
||
|
|
c = (c * 16) + HEXVALUE (*s);
|
||
|
|
/* \x followed by non-hex digits is passed through unchanged */
|
||
|
|
if (temp == 3)
|
||
|
|
{
|
||
|
|
*r++ = '\\';
|
||
|
|
c = 'x';
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case '\\':
|
||
|
|
break;
|
||
|
|
case '\'':
|
||
|
|
if (for_echo)
|
||
|
|
*r++ = '\\';
|
||
|
|
break;
|
||
|
|
case 'c':
|
||
|
|
if (sawc)
|
||
|
|
{
|
||
|
|
*sawc = 1;
|
||
|
|
*r = '\0';
|
||
|
|
if (rlen)
|
||
|
|
*rlen = r - ret;
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
default: *r++ = '\\'; break;
|
||
|
|
}
|
||
|
|
*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;
|
||
|
|
{
|
||
|
|
char *r, *ret, *s, obuf[8];
|
||
|
|
int l, c, rsize, t;
|
||
|
|
|
||
|
|
if (str == 0 || *str == 0)
|
||
|
|
return ((char *)0);
|
||
|
|
|
||
|
|
l = strlen (str);
|
||
|
|
rsize = 2 * l + 4;
|
||
|
|
r = ret = xmalloc (rsize);
|
||
|
|
|
||
|
|
*r++ = '$';
|
||
|
|
*r++ = '\'';
|
||
|
|
|
||
|
|
for (s = str, l = 0; *s; s++)
|
||
|
|
{
|
||
|
|
c = *(unsigned char *)s;
|
||
|
|
l = 1; /* 1 == add backslash; 0 == no backslash */
|
||
|
|
switch (c)
|
||
|
|
{
|
||
|
|
case ESC: c = 'E'; break;
|
||
|
|
#ifdef __STDC__
|
||
|
|
case '\a': c = 'a'; break;
|
||
|
|
case '\v': c = 'v'; break;
|
||
|
|
#else
|
||
|
|
case '\007': c = 'a'; break;
|
||
|
|
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:
|
||
|
|
if (isprint (c) == 0)
|
||
|
|
{
|
||
|
|
sprintf (obuf, "\\%.3o", c);
|
||
|
|
t = r - ret;
|
||
|
|
RESIZE_MALLOCED_BUFFER (ret, t, 5, rsize, 16);
|
||
|
|
r = ret + t; /* in case reallocated */
|
||
|
|
for (t = 0; t < 4; t++)
|
||
|
|
*r++ = obuf[t];
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
l = 0;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (l)
|
||
|
|
*r++ = '\\';
|
||
|
|
*r++ = c;
|
||
|
|
}
|
||
|
|
|
||
|
|
*r++ = '\'';
|
||
|
|
*r = '\0';
|
||
|
|
if (rlen)
|
||
|
|
*rlen = r - ret;
|
||
|
|
return ret;
|
||
|
|
}
|