1c6c9aed4Sab196087 /*
2c6c9aed4Sab196087 * CDDL HEADER START
3c6c9aed4Sab196087 *
4c6c9aed4Sab196087 * The contents of this file are subject to the terms of the
5c6c9aed4Sab196087 * Common Development and Distribution License (the "License").
6c6c9aed4Sab196087 * You may not use this file except in compliance with the License.
7c6c9aed4Sab196087 *
8c6c9aed4Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c6c9aed4Sab196087 * or http://www.opensolaris.org/os/licensing.
10c6c9aed4Sab196087 * See the License for the specific language governing permissions
11c6c9aed4Sab196087 * and limitations under the License.
12c6c9aed4Sab196087 *
13c6c9aed4Sab196087 * When distributing Covered Code, include this CDDL HEADER in each
14c6c9aed4Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c6c9aed4Sab196087 * If applicable, add the following below this CDDL HEADER, with the
16c6c9aed4Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying
17c6c9aed4Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner]
18c6c9aed4Sab196087 *
19c6c9aed4Sab196087 * CDDL HEADER END
20c6c9aed4Sab196087 */
21c6c9aed4Sab196087
22c6c9aed4Sab196087 /*
23*69112eddSAli Bahrami * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24c6c9aed4Sab196087 * Use is subject to license terms.
25c6c9aed4Sab196087 */
26c6c9aed4Sab196087
27c6c9aed4Sab196087
28c6c9aed4Sab196087 /*
29c6c9aed4Sab196087 * Translate a string into C literal string constant notation.
30c6c9aed4Sab196087 */
31c6c9aed4Sab196087
32c6c9aed4Sab196087 #include <stdio.h>
33c6c9aed4Sab196087 #include <ctype.h>
34c6c9aed4Sab196087 #include <_conv.h>
35c6c9aed4Sab196087 #include <c_literal_msg.h>
36c6c9aed4Sab196087
37c6c9aed4Sab196087
38c6c9aed4Sab196087 /*
39c6c9aed4Sab196087 * Convert characters to the form used by the C language to represent
40c6c9aed4Sab196087 * literal strings:
41c6c9aed4Sab196087 * - Printable characters are shown as themselves
42c6c9aed4Sab196087 * - Convert special characters to their 2-character escaped forms:
43c6c9aed4Sab196087 * alert (bell) \a
44c6c9aed4Sab196087 * backspace \b
45c6c9aed4Sab196087 * formfeed \f
46c6c9aed4Sab196087 * newline \n
47c6c9aed4Sab196087 * return \r
48c6c9aed4Sab196087 * horizontal tab \t
49c6c9aed4Sab196087 * vertical tab \v
50c6c9aed4Sab196087 * backspace \\
51c6c9aed4Sab196087 * single quote \'
52c6c9aed4Sab196087 * double quote \"
53c6c9aed4Sab196087 * - Display other non-printable characters as 4-character escaped
54c6c9aed4Sab196087 * octal constants.
55c6c9aed4Sab196087 *
56c6c9aed4Sab196087 * entry:
57c6c9aed4Sab196087 * buf - Buffer of characters to be processed
58c6c9aed4Sab196087 * n # of characters in buf to be processed
59c6c9aed4Sab196087 * outfunc - Function to be called to move output characters.
60c6c9aed4Sab196087 * uvalue - User value. This argument is passed to outfunc without
61c6c9aed4Sab196087 * examination. The caller can use it to pass additional
62c6c9aed4Sab196087 * information required by the callback.
63c6c9aed4Sab196087 *
64c6c9aed4Sab196087 * exit:
65c6c9aed4Sab196087 * The string has been processed, with the resulting data passed
66c6c9aed4Sab196087 * to outfunc for processing.
67c6c9aed4Sab196087 */
68c6c9aed4Sab196087 void
conv_str_to_c_literal(const char * buf,size_t n,Conv_str_to_c_literal_func_t * outfunc,void * uvalue)69c6c9aed4Sab196087 conv_str_to_c_literal(const char *buf, size_t n,
70c6c9aed4Sab196087 Conv_str_to_c_literal_func_t *outfunc, void *uvalue)
71c6c9aed4Sab196087 {
72c6c9aed4Sab196087 char bs_buf[2]; /* For two-character backslash codes */
73c6c9aed4Sab196087 char octal_buf[10]; /* For \000 style octal constants */
74c6c9aed4Sab196087
75c6c9aed4Sab196087 bs_buf[0] = '\\';
76c6c9aed4Sab196087 while (n > 0) {
77c6c9aed4Sab196087 switch (*buf) {
78c6c9aed4Sab196087 case '\0':
79c6c9aed4Sab196087 bs_buf[1] = '0';
80c6c9aed4Sab196087 break;
81c6c9aed4Sab196087 case '\a':
82c6c9aed4Sab196087 bs_buf[1] = 'a';
83c6c9aed4Sab196087 break;
84c6c9aed4Sab196087 case '\b':
85c6c9aed4Sab196087 bs_buf[1] = 'b';
86c6c9aed4Sab196087 break;
87c6c9aed4Sab196087 case '\f':
88c6c9aed4Sab196087 bs_buf[1] = 'f';
89c6c9aed4Sab196087 break;
90c6c9aed4Sab196087 case '\n':
91c6c9aed4Sab196087 bs_buf[1] = 'n';
92c6c9aed4Sab196087 break;
93c6c9aed4Sab196087 case '\r':
94c6c9aed4Sab196087 bs_buf[1] = 'r';
95c6c9aed4Sab196087 break;
96c6c9aed4Sab196087 case '\t':
97c6c9aed4Sab196087 bs_buf[1] = 't';
98c6c9aed4Sab196087 break;
99c6c9aed4Sab196087 case '\v':
100c6c9aed4Sab196087 bs_buf[1] = 'v';
101c6c9aed4Sab196087 break;
102c6c9aed4Sab196087 case '\\':
103c6c9aed4Sab196087 bs_buf[1] = '\\';
104c6c9aed4Sab196087 break;
105c6c9aed4Sab196087 case '\'':
106c6c9aed4Sab196087 bs_buf[1] = '\'';
107c6c9aed4Sab196087 break;
108c6c9aed4Sab196087 case '"':
109c6c9aed4Sab196087 bs_buf[1] = '"';
110c6c9aed4Sab196087 break;
111c6c9aed4Sab196087 default:
112c6c9aed4Sab196087 bs_buf[1] = '\0';
113c6c9aed4Sab196087 }
114c6c9aed4Sab196087
115c6c9aed4Sab196087 if (bs_buf[1] != '\0') {
116c6c9aed4Sab196087 (*outfunc)(bs_buf, 2, uvalue);
117c6c9aed4Sab196087 buf++;
118c6c9aed4Sab196087 n--;
119c6c9aed4Sab196087 } else if (isprint(*buf)) {
120c6c9aed4Sab196087 /*
121c6c9aed4Sab196087 * Output the entire sequence of printable
122c6c9aed4Sab196087 * characters in a single shot.
123c6c9aed4Sab196087 */
124c6c9aed4Sab196087 const char *start = buf;
125c6c9aed4Sab196087 size_t outlen = 0;
126c6c9aed4Sab196087
127c6c9aed4Sab196087 for (start = buf; (n > 0) && isprint(*buf); buf++, n--)
128c6c9aed4Sab196087 outlen++;
129c6c9aed4Sab196087 (*outfunc)(start, outlen, uvalue);
130c6c9aed4Sab196087 } else {
131c6c9aed4Sab196087 /* Generic unprintable character: Use octal notation */
132c6c9aed4Sab196087 (void) snprintf(octal_buf, sizeof (octal_buf),
1331da7e599SAli Bahrami MSG_ORIG(MSG_FMT_OCTCONST), (uchar_t)*buf);
134c6c9aed4Sab196087 (*outfunc)(octal_buf, strlen(octal_buf), uvalue);
135c6c9aed4Sab196087 buf++;
136c6c9aed4Sab196087 n--;
137c6c9aed4Sab196087 }
138c6c9aed4Sab196087 }
139c6c9aed4Sab196087 }
140*69112eddSAli Bahrami
141*69112eddSAli Bahrami /*
142*69112eddSAli Bahrami * Given the pointer to the character following a '\' character in
143*69112eddSAli Bahrami * a C style literal, return the ASCII character code it represents,
144*69112eddSAli Bahrami * and advance the string pointer to the character following the last
145*69112eddSAli Bahrami * character in the escape sequence.
146*69112eddSAli Bahrami *
147*69112eddSAli Bahrami * entry:
148*69112eddSAli Bahrami * str - Address of string pointer to first character following
149*69112eddSAli Bahrami * the backslash.
150*69112eddSAli Bahrami *
151*69112eddSAli Bahrami * exit:
152*69112eddSAli Bahrami * If the character is not valid, -1 is returned. Otherwise
153*69112eddSAli Bahrami * it returns the ASCII code for the translated character, and
154*69112eddSAli Bahrami * *str has been advanced.
155*69112eddSAli Bahrami */
156*69112eddSAli Bahrami int
conv_translate_c_esc(char ** str)157*69112eddSAli Bahrami conv_translate_c_esc(char **str)
158*69112eddSAli Bahrami {
159*69112eddSAli Bahrami char *s = *str;
160*69112eddSAli Bahrami int ch, i;
161*69112eddSAli Bahrami
162*69112eddSAli Bahrami ch = *s++;
163*69112eddSAli Bahrami switch (ch) {
164*69112eddSAli Bahrami case 'a':
165*69112eddSAli Bahrami ch = '\a';
166*69112eddSAli Bahrami break;
167*69112eddSAli Bahrami case 'b':
168*69112eddSAli Bahrami ch = '\b';
169*69112eddSAli Bahrami break;
170*69112eddSAli Bahrami case 'f':
171*69112eddSAli Bahrami ch = '\f';
172*69112eddSAli Bahrami break;
173*69112eddSAli Bahrami case 'n':
174*69112eddSAli Bahrami ch = '\n';
175*69112eddSAli Bahrami break;
176*69112eddSAli Bahrami case 'r':
177*69112eddSAli Bahrami ch = '\r';
178*69112eddSAli Bahrami break;
179*69112eddSAli Bahrami case 't':
180*69112eddSAli Bahrami ch = '\t';
181*69112eddSAli Bahrami break;
182*69112eddSAli Bahrami case 'v':
183*69112eddSAli Bahrami ch = '\v';
184*69112eddSAli Bahrami break;
185*69112eddSAli Bahrami
186*69112eddSAli Bahrami case '0':
187*69112eddSAli Bahrami case '1':
188*69112eddSAli Bahrami case '2':
189*69112eddSAli Bahrami case '3':
190*69112eddSAli Bahrami case '4':
191*69112eddSAli Bahrami case '5':
192*69112eddSAli Bahrami case '6':
193*69112eddSAli Bahrami case '7':
194*69112eddSAli Bahrami /* Octal constant: There can be up to 3 digits */
195*69112eddSAli Bahrami ch -= '0';
196*69112eddSAli Bahrami for (i = 0; i < 2; i++) {
197*69112eddSAli Bahrami if ((*s < '0') || (*s > '7'))
198*69112eddSAli Bahrami break;
199*69112eddSAli Bahrami ch = (ch << 3) + (*s++ - '0');
200*69112eddSAli Bahrami }
201*69112eddSAli Bahrami break;
202*69112eddSAli Bahrami
203*69112eddSAli Bahrami /*
204*69112eddSAli Bahrami * There are some cases where ch already has the desired value.
205*69112eddSAli Bahrami * These cases exist simply to remove the special meaning that
206*69112eddSAli Bahrami * character would otherwise have. We need to match them to
207*69112eddSAli Bahrami * prevent them from falling into the default error case.
208*69112eddSAli Bahrami */
209*69112eddSAli Bahrami case '\\':
210*69112eddSAli Bahrami case '\'':
211*69112eddSAli Bahrami case '"':
212*69112eddSAli Bahrami break;
213*69112eddSAli Bahrami
214*69112eddSAli Bahrami default:
215*69112eddSAli Bahrami ch = -1;
216*69112eddSAli Bahrami break;
217*69112eddSAli Bahrami }
218*69112eddSAli Bahrami
219*69112eddSAli Bahrami *str = s;
220*69112eddSAli Bahrami return (ch);
221*69112eddSAli Bahrami }
222