166 lines
3.4 KiB
C
166 lines
3.4 KiB
C
/*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* Jordan K. Hubbard
|
|
* 29 August 1998
|
|
*
|
|
* $FreeBSD$
|
|
*
|
|
* Routine for doing backslash elimination.
|
|
*/
|
|
|
|
#include <stand.h>
|
|
#include <string.h>
|
|
|
|
#define DIGIT(x) (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
|
|
|
|
/*
|
|
* backslash: Return malloc'd copy of str with all standard "backslash
|
|
* processing" done on it. Original can be free'd if desired.
|
|
*/
|
|
char *
|
|
backslash(char *str)
|
|
{
|
|
/*
|
|
* Remove backslashes from the strings. Turn \040 etc. into a single
|
|
* character (we allow eight bit values). Currently NUL is not
|
|
* allowed.
|
|
*
|
|
* Turn "\n" and "\t" into '\n' and '\t' characters. Etc.
|
|
*
|
|
*/
|
|
char *new_str;
|
|
int seenbs = 0;
|
|
int i = 0;
|
|
|
|
if ((new_str = strdup(str)) == NULL)
|
|
return NULL;
|
|
|
|
while (*str) {
|
|
if (seenbs) {
|
|
seenbs = 0;
|
|
switch (*str) {
|
|
case '\\':
|
|
new_str[i++] = '\\';
|
|
str++;
|
|
break;
|
|
|
|
/* preserve backslashed quotes, dollar signs */
|
|
case '\'':
|
|
case '"':
|
|
case '$':
|
|
new_str[i++] = '\\';
|
|
new_str[i++] = *str++;
|
|
break;
|
|
|
|
case 'b':
|
|
new_str[i++] = '\b';
|
|
str++;
|
|
break;
|
|
|
|
case 'f':
|
|
new_str[i++] = '\f';
|
|
str++;
|
|
break;
|
|
|
|
case 'r':
|
|
new_str[i++] = '\r';
|
|
str++;
|
|
break;
|
|
|
|
case 'n':
|
|
new_str[i++] = '\n';
|
|
str++;
|
|
break;
|
|
|
|
case 's':
|
|
new_str[i++] = ' ';
|
|
str++;
|
|
break;
|
|
|
|
case 't':
|
|
new_str[i++] = '\t';
|
|
str++;
|
|
break;
|
|
|
|
case 'v':
|
|
new_str[i++] = '\13';
|
|
str++;
|
|
break;
|
|
|
|
case 'z':
|
|
str++;
|
|
break;
|
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
case '5': case '6': case '7': case '8': case '9': {
|
|
char val;
|
|
|
|
/* Three digit octal constant? */
|
|
if (*str >= '0' && *str <= '3' &&
|
|
*(str + 1) >= '0' && *(str + 1) <= '7' &&
|
|
*(str + 2) >= '0' && *(str + 2) <= '7') {
|
|
|
|
val = (DIGIT(*str) << 6) + (DIGIT(*(str + 1)) << 3) +
|
|
DIGIT(*(str + 2));
|
|
|
|
/* Allow null value if user really wants to shoot
|
|
at feet, but beware! */
|
|
new_str[i++] = val;
|
|
str += 3;
|
|
break;
|
|
}
|
|
|
|
/* One or two digit hex constant?
|
|
* If two are there they will both be taken.
|
|
* Use \z to split them up if this is not wanted.
|
|
*/
|
|
if (*str == '0' &&
|
|
(*(str + 1) == 'x' || *(str + 1) == 'X') &&
|
|
isxdigit(*(str + 2))) {
|
|
val = DIGIT(*(str + 2));
|
|
if (isxdigit(*(str + 3))) {
|
|
val = (val << 4) + DIGIT(*(str + 3));
|
|
str += 4;
|
|
}
|
|
else
|
|
str += 3;
|
|
/* Yep, allow null value here too */
|
|
new_str[i++] = val;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
new_str[i++] = *str++;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (*str == '\\') {
|
|
seenbs = 1;
|
|
str++;
|
|
}
|
|
else
|
|
new_str[i++] = *str++;
|
|
}
|
|
}
|
|
|
|
if (seenbs) {
|
|
/*
|
|
* The final character was a '\'. Put it in as a single backslash.
|
|
*/
|
|
new_str[i++] = '\\';
|
|
}
|
|
new_str[i] = '\0';
|
|
return new_str;
|
|
}
|