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