Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / ia64 / stand / common / interp_backslash.c
blobd68afd0a2c2d69a8aea82e0b68a53fd0dc18edac
1 /* $NetBSD: interp_backslash.c,v 1.2 2006/04/22 07:58:53 cherry Exp $ */
3 /*-
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * Jordan K. Hubbard
14 * 29 August 1998
16 * Routine for doing backslash elimination.
19 #include <sys/cdefs.h>
20 /* __FBSDID("$FreeBSD: src/sys/boot/common/interp_backslash.c,v 1.6 2003/08/25 23:30:41 obrien Exp $"); */
22 #include <lib/libsa/stand.h>
23 #include <lib/libsa/loadfile.h>
24 #include <lib/libkern/libkern.h>
26 #include "bootstrap.h"
28 #define DIGIT(x) (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
31 * backslash: Return malloc'd copy of str with all standard "backslash
32 * processing" done on it. Original can be free'd if desired.
34 char *
35 backslash(char *str)
38 * Remove backslashes from the strings. Turn \040 etc. into a single
39 * character (we allow eight bit values). Currently NUL is not
40 * allowed.
42 * Turn "\n" and "\t" into '\n' and '\t' characters. Etc.
45 char *new_str;
46 int seenbs = 0;
47 int i = 0;
49 if ((new_str = strdup(str)) == NULL)
50 return NULL;
52 while (*str) {
53 if (seenbs) {
54 seenbs = 0;
55 switch (*str) {
56 case '\\':
57 new_str[i++] = '\\';
58 str++;
59 break;
61 /* preserve backslashed quotes, dollar signs */
62 case '\'':
63 case '"':
64 case '$':
65 new_str[i++] = '\\';
66 new_str[i++] = *str++;
67 break;
69 case 'b':
70 new_str[i++] = '\b';
71 str++;
72 break;
74 case 'f':
75 new_str[i++] = '\f';
76 str++;
77 break;
79 case 'r':
80 new_str[i++] = '\r';
81 str++;
82 break;
84 case 'n':
85 new_str[i++] = '\n';
86 str++;
87 break;
89 case 's':
90 new_str[i++] = ' ';
91 str++;
92 break;
94 case 't':
95 new_str[i++] = '\t';
96 str++;
97 break;
99 case 'v':
100 new_str[i++] = '\13';
101 str++;
102 break;
104 case 'z':
105 str++;
106 break;
108 case '0': case '1': case '2': case '3': case '4':
109 case '5': case '6': case '7': case '8': case '9': {
110 char val;
112 /* Three digit octal constant? */
113 if (*str >= '0' && *str <= '3' &&
114 *(str + 1) >= '0' && *(str + 1) <= '7' &&
115 *(str + 2) >= '0' && *(str + 2) <= '7') {
117 val = (DIGIT(*str) << 6) + (DIGIT(*(str + 1)) << 3) +
118 DIGIT(*(str + 2));
120 /* Allow null value if user really wants to shoot
121 at feet, but beware! */
122 new_str[i++] = val;
123 str += 3;
124 break;
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 wanted.
131 if (*str == '0' &&
132 (*(str + 1) == 'x' || *(str + 1) == 'X') &&
133 isxdigit(*(str + 2))) {
134 val = DIGIT(*(str + 2));
135 if (isxdigit(*(str + 3))) {
136 val = (val << 4) + DIGIT(*(str + 3));
137 str += 4;
139 else
140 str += 3;
141 /* Yep, allow null value here too */
142 new_str[i++] = val;
143 break;
146 break;
148 default:
149 new_str[i++] = *str++;
150 break;
153 else {
154 if (*str == '\\') {
155 seenbs = 1;
156 str++;
158 else
159 new_str[i++] = *str++;
163 if (seenbs) {
165 * The final character was a '\'. Put it in as a single backslash.
167 new_str[i++] = '\\';
169 new_str[i] = '\0';
170 return new_str;