boot/loader: Fix the 'crc' command to the intended code.
[dragonfly.git] / sys / boot / common / interp_backslash.c
blob2308af0223ce4828e289da229405bc406980a07d
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.
11 * Jordan K. Hubbard
12 * 29 August 1998
14 * Routine for doing backslash elimination.
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 $
20 #include <stand.h>
21 #include <string.h>
22 #include "bootstrap.h"
24 #define DIGIT(x) (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
27 * backslash: Return malloc'd copy of str with all standard "backslash
28 * processing" done on it. Original can be free'd if desired.
30 char *
31 backslash(char *str)
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. Also escape as needed.
38 * Turn "\n" and "\t" into '\n' and '\t' characters. Etc.
41 char *new_str;
42 int seenbs = 0;
43 int i = 0;
44 int j = 0;
46 for (i = 0; str[i]; ++i) {
47 if (str[i] == '\'' ||
48 str[i] == '"' ||
49 str[i] == '$') {
50 ++j;
53 j += i + 2; /* terminator + possible final backslash */
55 new_str = malloc(j);
57 i = 0;
58 while (*str) {
59 if (seenbs) {
60 seenbs = 0;
61 switch (*str) {
62 case '\\':
63 new_str[i++] = '\\';
64 str++;
65 break;
67 /* preserve backslashed quotes, dollar signs */
68 case '\'':
69 case '"':
70 case '$':
71 new_str[i++] = '\\';
72 new_str[i++] = *str++;
73 break;
75 case 'b':
76 new_str[i++] = '\b';
77 str++;
78 break;
80 case 'f':
81 new_str[i++] = '\f';
82 str++;
83 break;
85 case 'r':
86 new_str[i++] = '\r';
87 str++;
88 break;
90 case 'n':
91 new_str[i++] = '\n';
92 str++;
93 break;
95 case 's':
96 new_str[i++] = ' ';
97 str++;
98 break;
100 case 't':
101 new_str[i++] = '\t';
102 str++;
103 break;
105 case 'v':
106 new_str[i++] = '\13';
107 str++;
108 break;
110 case 'z':
111 str++;
112 break;
114 case '0': case '1': case '2': case '3': case '4':
115 case '5': case '6': case '7': case '8': case '9': {
116 char val;
118 /* Three digit octal constant? */
119 if (*str >= '0' && *str <= '3' &&
120 *(str + 1) >= '0' && *(str + 1) <= '7' &&
121 *(str + 2) >= '0' && *(str + 2) <= '7') {
123 val = (DIGIT(*str) << 6) + (DIGIT(*(str + 1)) << 3) +
124 DIGIT(*(str + 2));
126 /* Allow null value if user really wants to shoot
127 at feet, but beware! */
128 new_str[i++] = val;
129 str += 3;
130 break;
133 /* One or two digit hex constant?
134 * If two are there they will both be taken.
135 * Use \z to split them up if this is not wanted.
137 if (*str == '0' &&
138 (*(str + 1) == 'x' || *(str + 1) == 'X') &&
139 isxdigit(*(str + 2))) {
140 val = DIGIT(*(str + 2));
141 if (isxdigit(*(str + 3))) {
142 val = (val << 4) + DIGIT(*(str + 3));
143 str += 4;
145 else
146 str += 3;
147 /* Yep, allow null value here too */
148 new_str[i++] = val;
149 break;
152 break;
154 default:
155 new_str[i++] = *str++;
156 break;
159 else {
160 if (*str == '\\') {
161 seenbs = 1;
162 str++;
163 } else {
164 new_str[i++] = *str++;
169 if (seenbs) {
171 * The final character was a '\'. Put it in as a single backslash.
173 new_str[i++] = '\\';
175 new_str[i] = 0;
176 if (i >= j)
177 panic("bls");
179 return new_str;