c_literal.c revision 8747:73be8d78d904
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28/*
29 * Translate a string into C literal string constant notation.
30 */
31
32#include	<stdio.h>
33#include	<ctype.h>
34#include	<_conv.h>
35#include	<c_literal_msg.h>
36
37
38/*
39 * Convert characters to the form used by the C language to represent
40 * literal strings:
41 *	- Printable characters are shown as themselves
42 *	- Convert special characters to their 2-character escaped forms:
43 *		alert (bell)	\a
44 *		backspace	\b
45 *		formfeed	\f
46 *		newline		\n
47 *		return		\r
48 *		horizontal tab	\t
49 *		vertical tab	\v
50 *		backspace	\\
51 *		single quote	\'
52 *		double quote	\"
53 *	- Display other non-printable characters as 4-character escaped
54 *		octal constants.
55 *
56 * entry:
57 *	buf - Buffer of characters to be processed
58 *	n # of characters in buf to be processed
59 *	outfunc - Function to be called to move output characters.
60 *	uvalue - User value. This argument is passed to outfunc without
61 *		examination. The caller can use it to pass additional
62 *		information required by the callback.
63 *
64 * exit:
65 *	The string has been processed, with the resulting data passed
66 *	to outfunc for processing.
67 */
68void
69conv_str_to_c_literal(const char *buf, size_t n,
70    Conv_str_to_c_literal_func_t *outfunc, void *uvalue)
71{
72	char	bs_buf[2];	/* For two-character backslash codes */
73	char	octal_buf[10];	/* For \000 style octal constants */
74
75	bs_buf[0] = '\\';
76	while (n > 0) {
77		switch (*buf) {
78		case '\0':
79			bs_buf[1] = '0';
80			break;
81		case '\a':
82			bs_buf[1] = 'a';
83			break;
84		case '\b':
85			bs_buf[1] = 'b';
86			break;
87		case '\f':
88			bs_buf[1] = 'f';
89			break;
90		case '\n':
91			bs_buf[1] = 'n';
92			break;
93		case '\r':
94			bs_buf[1] = 'r';
95			break;
96		case '\t':
97			bs_buf[1] = 't';
98			break;
99		case '\v':
100			bs_buf[1] = 'v';
101			break;
102		case '\\':
103			bs_buf[1] = '\\';
104			break;
105		case '\'':
106			bs_buf[1] = '\'';
107			break;
108		case '"':
109			bs_buf[1] = '"';
110			break;
111		default:
112			bs_buf[1] = '\0';
113		}
114
115		if (bs_buf[1] != '\0') {
116			(*outfunc)(bs_buf, 2, uvalue);
117			buf++;
118			n--;
119		} else if (isprint(*buf)) {
120			/*
121			 * Output the entire sequence of printable
122			 * characters in a single shot.
123			 */
124			const char	*start = buf;
125			size_t		outlen = 0;
126
127			for (start = buf; (n > 0) && isprint(*buf); buf++, n--)
128				outlen++;
129			(*outfunc)(start, outlen, uvalue);
130		} else {
131			/* Generic unprintable character: Use octal notation */
132			(void) snprintf(octal_buf, sizeof (octal_buf),
133			    MSG_ORIG(MSG_FMT_OCTCONST), (uchar_t)*buf);
134			(*outfunc)(octal_buf, strlen(octal_buf), uvalue);
135			buf++;
136			n--;
137		}
138	}
139}
140