/* Expand escape sequences in a string. Copyright (C) 1995-1997, 2000-2007, 2012, 2018-2019 Free Software Foundation, Inc. Written by Ulrich Drepper , May 1995. This program 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. This program 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 this program. If not, see . */ /* Expand some escape sequences found in the argument string. If backslash_c_seen is != NULL, '\c' sequences are recognized and have the effect of setting *backslash_c_seen to true. Returns either the argument string or a freshly allocated string. */ static const char * expand_escapes (const char *str, bool *backslash_c_seen) { const char *cp = str; /* Find the location of the first escape sequence. If the string contains no escape sequences, return it right away. */ for (;;) { while (cp[0] != '\0' && cp[0] != '\\') ++cp; if (cp[0] == '\0') /* The argument string contains no escape sequence. */ return str; /* Found a backslash. */ if (cp[1] == '\0') return str; if (strchr ("abcfnrtv\\01234567", cp[1]) != NULL) break; ++cp; } { char *retval = XNMALLOC (strlen (str), char); memcpy (retval, str, cp - str); { char *rp = retval + (cp - str); do { /* Here cp[0] == '\\'. */ switch (*++cp) { case 'a': /* alert */ *rp++ = '\a'; ++cp; break; case 'b': /* backspace */ *rp++ = '\b'; ++cp; break; case 'f': /* form feed */ *rp++ = '\f'; ++cp; break; case 'n': /* new line */ *rp++ = '\n'; ++cp; break; case 'r': /* carriage return */ *rp++ = '\r'; ++cp; break; case 't': /* horizontal tab */ *rp++ = '\t'; ++cp; break; case 'v': /* vertical tab */ *rp++ = '\v'; ++cp; break; case '\\': *rp++ = '\\'; ++cp; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int ch = *cp++ - '0'; if (*cp >= '0' && *cp <= '7') { ch *= 8; ch += *cp++ - '0'; if (*cp >= '0' && *cp <= '7') { ch *= 8; ch += *cp++ - '0'; } } *rp++ = ch; } break; case 'c': if (backslash_c_seen != NULL) { *backslash_c_seen = true; ++cp; break; } /* FALLTHROUGH */ default: *rp++ = '\\'; break; } /* Find the next escape sequence. */ while (cp[0] != '\0' && cp[0] != '\\') *rp++ = *cp++; } while (cp[0] != '\0'); /* Terminate the resulting string. */ *rp = '\0'; } return retval; } }