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