xref: /illumos-gate/usr/src/cmd/sgs/libconv/common/c_literal.c (revision c6c9aed4d309e3d11be652b85e3bf8bb72f20c87)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 
30 /*
31  * Translate a string into C literal string constant notation.
32  */
33 
34 #include	<stdio.h>
35 #include	<ctype.h>
36 #include	<_conv.h>
37 #include	<c_literal_msg.h>
38 
39 
40 /*
41  * Convert characters to the form used by the C language to represent
42  * literal strings:
43  *	- Printable characters are shown as themselves
44  *	- Convert special characters to their 2-character escaped forms:
45  *		alert (bell)	\a
46  *		backspace	\b
47  *		formfeed	\f
48  *		newline		\n
49  *		return		\r
50  *		horizontal tab	\t
51  *		vertical tab	\v
52  *		backspace	\\
53  *		single quote	\'
54  *		double quote	\"
55  *	- Display other non-printable characters as 4-character escaped
56  *		octal constants.
57  *
58  * entry:
59  *	buf - Buffer of characters to be processed
60  *	n # of characters in buf to be processed
61  *	outfunc - Function to be called to move output characters.
62  *	uvalue - User value. This argument is passed to outfunc without
63  *		examination. The caller can use it to pass additional
64  *		information required by the callback.
65  *
66  * exit:
67  *	The string has been processed, with the resulting data passed
68  *	to outfunc for processing.
69  */
70 void
71 conv_str_to_c_literal(const char *buf, size_t n,
72     Conv_str_to_c_literal_func_t *outfunc, void *uvalue)
73 {
74 	char	bs_buf[2];	/* For two-character backslash codes */
75 	char	octal_buf[10];	/* For \000 style octal constants */
76 
77 	bs_buf[0] = '\\';
78 	while (n > 0) {
79 		switch (*buf) {
80 		case '\0':
81 			bs_buf[1] = '0';
82 			break;
83 		case '\a':
84 			bs_buf[1] = 'a';
85 			break;
86 		case '\b':
87 			bs_buf[1] = 'b';
88 			break;
89 		case '\f':
90 			bs_buf[1] = 'f';
91 			break;
92 		case '\n':
93 			bs_buf[1] = 'n';
94 			break;
95 		case '\r':
96 			bs_buf[1] = 'r';
97 			break;
98 		case '\t':
99 			bs_buf[1] = 't';
100 			break;
101 		case '\v':
102 			bs_buf[1] = 'v';
103 			break;
104 		case '\\':
105 			bs_buf[1] = '\\';
106 			break;
107 		case '\'':
108 			bs_buf[1] = '\'';
109 			break;
110 		case '"':
111 			bs_buf[1] = '"';
112 			break;
113 		default:
114 			bs_buf[1] = '\0';
115 		}
116 
117 		if (bs_buf[1] != '\0') {
118 			(*outfunc)(bs_buf, 2, uvalue);
119 			buf++;
120 			n--;
121 		} else if (isprint(*buf)) {
122 			/*
123 			 * Output the entire sequence of printable
124 			 * characters in a single shot.
125 			 */
126 			const char	*start = buf;
127 			size_t		outlen = 0;
128 
129 			for (start = buf; (n > 0) && isprint(*buf); buf++, n--)
130 				outlen++;
131 			(*outfunc)(start, outlen, uvalue);
132 		} else {
133 			/* Generic unprintable character: Use octal notation */
134 			(void) snprintf(octal_buf, sizeof (octal_buf),
135 			    MSG_ORIG(MSG_FMT_OCTCONST), *buf);
136 			(*outfunc)(octal_buf, strlen(octal_buf), uvalue);
137 			buf++;
138 			n--;
139 		}
140 	}
141 }
142