Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/common/interp_backslash.c
34677 views
1
/*-
2
* Redistribution and use in source and binary forms, with or without
3
* modification, are permitted provided that the following conditions
4
* are met:
5
* 1. Redistributions of source code must retain the above copyright
6
* notice, this list of conditions and the following disclaimer.
7
* 2. Redistributions in binary form must reproduce the above copyright
8
* notice, this list of conditions and the following disclaimer in the
9
* documentation and/or other materials provided with the distribution.
10
*
11
* Jordan K. Hubbard
12
* 29 August 1998
13
*
14
* Routine for doing backslash elimination.
15
*/
16
17
#include <stand.h>
18
#include <string.h>
19
#include "bootstrap.h"
20
21
#define DIGIT(x) (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
22
23
/*
24
* backslash: Return malloc'd copy of str with all standard "backslash
25
* processing" done on it. Original can be free'd if desired.
26
*/
27
char *
28
backslash(const char *str)
29
{
30
/*
31
* Remove backslashes from the strings. Turn \040 etc. into a single
32
* character (we allow eight bit values). Currently NUL is not
33
* allowed.
34
*
35
* Turn "\n" and "\t" into '\n' and '\t' characters. Etc.
36
*
37
*/
38
char *new_str;
39
int seenbs = 0;
40
int i = 0;
41
42
if ((new_str = strdup(str)) == NULL)
43
return NULL;
44
45
while (*str) {
46
if (seenbs) {
47
seenbs = 0;
48
switch (*str) {
49
case '\\':
50
new_str[i++] = '\\';
51
str++;
52
break;
53
54
/* preserve backslashed quotes, dollar signs */
55
case '\'':
56
case '"':
57
case '$':
58
new_str[i++] = '\\';
59
new_str[i++] = *str++;
60
break;
61
62
case 'b':
63
new_str[i++] = '\b';
64
str++;
65
break;
66
67
case 'f':
68
new_str[i++] = '\f';
69
str++;
70
break;
71
72
case 'r':
73
new_str[i++] = '\r';
74
str++;
75
break;
76
77
case 'n':
78
new_str[i++] = '\n';
79
str++;
80
break;
81
82
case 's':
83
new_str[i++] = ' ';
84
str++;
85
break;
86
87
case 't':
88
new_str[i++] = '\t';
89
str++;
90
break;
91
92
case 'v':
93
new_str[i++] = '\13';
94
str++;
95
break;
96
97
case 'z':
98
str++;
99
break;
100
101
case '0': case '1': case '2': case '3': case '4':
102
case '5': case '6': case '7': case '8': case '9': {
103
char val;
104
105
/* Three digit octal constant? */
106
if (*str >= '0' && *str <= '3' &&
107
*(str + 1) >= '0' && *(str + 1) <= '7' &&
108
*(str + 2) >= '0' && *(str + 2) <= '7') {
109
110
val = (DIGIT(*str) << 6) + (DIGIT(*(str + 1)) << 3) +
111
DIGIT(*(str + 2));
112
113
/* Allow null value if user really wants to shoot
114
at feet, but beware! */
115
new_str[i++] = val;
116
str += 3;
117
break;
118
}
119
120
/* One or two digit hex constant?
121
* If two are there they will both be taken.
122
* Use \z to split them up if this is not wanted.
123
*/
124
if (*str == '0' &&
125
(*(str + 1) == 'x' || *(str + 1) == 'X') &&
126
isxdigit(*(str + 2))) {
127
val = DIGIT(*(str + 2));
128
if (isxdigit(*(str + 3))) {
129
val = (val << 4) + DIGIT(*(str + 3));
130
str += 4;
131
}
132
else
133
str += 3;
134
/* Yep, allow null value here too */
135
new_str[i++] = val;
136
break;
137
}
138
}
139
break;
140
141
default:
142
new_str[i++] = *str++;
143
break;
144
}
145
}
146
else {
147
if (*str == '\\') {
148
seenbs = 1;
149
str++;
150
}
151
else
152
new_str[i++] = *str++;
153
}
154
}
155
156
if (seenbs) {
157
/*
158
* The final character was a '\'. Put it in as a single backslash.
159
*/
160
new_str[i++] = '\\';
161
}
162
new_str[i] = '\0';
163
return new_str;
164
}
165
166