/* strvis.c - make unsafe graphical characters in a string visible. */
/* Copyright (C) 2022 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 3 of the License, 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. If not, see .
*/
/* This is a stripped-down version suitable for the shell's use. */
#include
#include
#include "bashansi.h"
#include
#include "chartypes.h"
#include "bashintl.h"
#include "shmbutil.h"
#define SAFECHAR(c) ((c) == ' ' || (c) == '\t')
#ifndef RUBOUT
#define RUBOUT 0x7f
#endif
#ifndef CTRL_CHAR
#define CTRL_CHAR(c) ((c) < 0x20)
#endif
#ifndef META_CHAR
#define META_CHAR(c) ((c) > 0x7f && (c) <= UCHAR_MAX)
#endif
#ifndef UNCTRL
#define UNCTRL(c) (TOUPPER ((c) | 0x40))
#endif
#ifndef UNMETA
#define UNMETA(c) ((c) & 0x7f)
#endif
int
sh_charvis (s, sindp, slen, ret, rindp)
const char *s;
size_t *sindp;
size_t slen;
char *ret;
size_t *rindp;
{
unsigned char c;
size_t si, ri;
const char *send;
DECLARE_MBSTATE;
si = *sindp;
ri = *rindp;
c = s[*sindp];
#if defined (HANDLE_MULTIBYTE)
send = (locale_mb_cur_max > 1) ? s + slen : 0;
#else
send = 0;
#endif
if (SAFECHAR (c))
{
ret[ri++] = c;
si++;
}
else if (c == RUBOUT)
{
ret[ri++] = '^';
ret[ri++] = '?';
si++;
}
else if (CTRL_CHAR (c))
{
ret[ri++] = '^';
ret[ri++] = UNCTRL (c);
si++;
}
#if defined (HANDLE_MULTIBYTE)
else if (locale_utf8locale && (c & 0x80))
COPY_CHAR_I (ret, ri, s, send, si);
else if (locale_mb_cur_max > 1 && is_basic (c) == 0)
COPY_CHAR_I (ret, ri, s, send, si);
#endif
else if (META_CHAR (c))
{
ret[ri++] = 'M';
ret[ri++] = '-';
ret[ri++] = UNMETA (c);
si++;
}
else
ret[ri++] = s[si++];
*sindp = si;
*rindp = ri;
return si;
}
/* Return a new string with `unsafe' non-graphical characters in S rendered
in a visible way. */
char *
sh_strvis (string)
const char *string;
{
size_t slen, sind;
char *ret;
size_t retind, retsize;
unsigned char c;
DECLARE_MBSTATE;
if (string == 0)
return 0;
if (*string == '\0')
{
if ((ret = (char *)malloc (1)) == 0)
return 0;
ret[0] = '\0';
return ret;
}
slen = strlen (string);
retsize = 3 * slen + 1;
ret = (char *)malloc (retsize);
if (ret == 0)
return 0;
retind = 0;
sind = 0;
while (string[sind])
sind = sh_charvis (string, &sind, slen, ret, &retind);
ret[retind] = '\0';
return ret;
}