aboutsummaryrefslogtreecommitdiffstats
path: root/lib/sh/strtrans.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sh/strtrans.c')
-rw-r--r--lib/sh/strtrans.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/lib/sh/strtrans.c b/lib/sh/strtrans.c
new file mode 100644
index 0000000..7005c46
--- /dev/null
+++ b/lib/sh/strtrans.c
@@ -0,0 +1,205 @@
+/* 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;
+}