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