• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Expand escape sequences in a string.
2    Copyright (C) 1995-1997, 2000-2007, 2012, 2018-2019 Free Software
3    Foundation, Inc.
4    Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, May 1995.
5 
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
18 
19 /* Expand some escape sequences found in the argument string.
20    If backslash_c_seen is != NULL, '\c' sequences are recognized and
21    have the effect of setting *backslash_c_seen to true.
22    Returns either the argument string or a freshly allocated string.  */
23 static const char *
expand_escapes(const char * str,bool * backslash_c_seen)24 expand_escapes (const char *str, bool *backslash_c_seen)
25 {
26   const char *cp = str;
27 
28   /* Find the location of the first escape sequence.
29      If the string contains no escape sequences, return it right away.  */
30   for (;;)
31     {
32       while (cp[0] != '\0' && cp[0] != '\\')
33         ++cp;
34       if (cp[0] == '\0')
35         /* The argument string contains no escape sequence.  */
36         return str;
37       /* Found a backslash.  */
38       if (cp[1] == '\0')
39         return str;
40       if (strchr ("abcfnrtv\\01234567", cp[1]) != NULL)
41         break;
42       ++cp;
43     }
44 
45   {
46     char *retval = XNMALLOC (strlen (str), char);
47 
48     memcpy (retval, str, cp - str);
49     {
50       char *rp = retval + (cp - str);
51 
52       do
53         {
54           /* Here cp[0] == '\\'.  */
55           switch (*++cp)
56             {
57             case 'a':               /* alert */
58               *rp++ = '\a';
59               ++cp;
60               break;
61             case 'b':               /* backspace */
62               *rp++ = '\b';
63               ++cp;
64               break;
65             case 'f':               /* form feed */
66               *rp++ = '\f';
67               ++cp;
68               break;
69             case 'n':               /* new line */
70               *rp++ = '\n';
71               ++cp;
72               break;
73             case 'r':               /* carriage return */
74               *rp++ = '\r';
75               ++cp;
76               break;
77             case 't':               /* horizontal tab */
78               *rp++ = '\t';
79               ++cp;
80               break;
81             case 'v':               /* vertical tab */
82               *rp++ = '\v';
83               ++cp;
84               break;
85             case '\\':
86               *rp++ = '\\';
87               ++cp;
88               break;
89             case '0': case '1': case '2': case '3':
90             case '4': case '5': case '6': case '7':
91               {
92                 int ch = *cp++ - '0';
93 
94                 if (*cp >= '0' && *cp <= '7')
95                   {
96                     ch *= 8;
97                     ch += *cp++ - '0';
98 
99                     if (*cp >= '0' && *cp <= '7')
100                       {
101                         ch *= 8;
102                         ch += *cp++ - '0';
103                       }
104                   }
105                 *rp++ = ch;
106               }
107               break;
108             case 'c':
109               if (backslash_c_seen != NULL)
110                 {
111                   *backslash_c_seen = true;
112                   ++cp;
113                   break;
114                 }
115               /* FALLTHROUGH */
116             default:
117               *rp++ = '\\';
118               break;
119             }
120 
121           /* Find the next escape sequence.  */
122           while (cp[0] != '\0' && cp[0] != '\\')
123             *rp++ = *cp++;
124         }
125       while (cp[0] != '\0');
126 
127       /* Terminate the resulting string.  */
128       *rp = '\0';
129     }
130 
131     return retval;
132   }
133 }
134