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 <sys/cdefs.h> 18 19 #include <stand.h> 20 #include <string.h> 21 #include "bootstrap.h" 22 23 #define DIGIT(x) \ 24 (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 */ 30 char * 31 backslash(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) + 114 (DIGIT(*(str + 1)) << 3) + 115 DIGIT(*(str + 2)); 116 117 /* 118 * Allow null value if user really 119 * wants to shoot at feet, but beware! 120 */ 121 new_str[i++] = val; 122 str += 3; 123 break; 124 } 125 126 /* 127 * One or two digit hex constant? 128 * If two are there they will both be taken. 129 * Use \z to split them up if this is not 130 * wanted. 131 */ 132 if (*str == '0' && 133 (*(str + 1) == 'x' || *(str + 1) == 'X') && 134 isxdigit(*(str + 2))) { 135 val = DIGIT(*(str + 2)); 136 if (isxdigit(*(str + 3))) { 137 val = (val << 4) + 138 DIGIT(*(str + 3)); 139 str += 4; 140 } else 141 str += 3; 142 /* Yep, allow null value here too */ 143 new_str[i++] = val; 144 break; 145 } 146 } 147 break; 148 149 default: 150 new_str[i++] = *str++; 151 break; 152 } 153 } else { 154 if (*str == '\\') { 155 seenbs = 1; 156 str++; 157 } else 158 new_str[i++] = *str++; 159 } 160 } 161 162 if (seenbs) { 163 /* 164 * The final character was a '\'. 165 * Put it in as a single backslash. 166 */ 167 new_str[i++] = '\\'; 168 } 169 new_str[i] = '\0'; 170 return (new_str); 171 } 172