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