1 /* $NetBSD: util.c,v 1.34 2011/08/29 14:44:21 joerg Exp $ */
4 * Copyright (c) 1989, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
38 static char sccsid
[] = "@(#)util.c 8.5 (Berkeley) 4/28/95";
40 __RCSID("$NetBSD: util.c,v 1.34 2011/08/29 14:44:21 joerg Exp $");
44 #include <sys/types.h>
61 safe_print(const char *src
)
67 flags
= VIS_NL
| VIS_OCTAL
| VIS_WHITE
;
72 if (len
!= 0 && SIZE_T_MAX
/len
<= 4) {
73 errx(EXIT_FAILURE
, "%s: name too long", src
);
77 name
= (char *)malloc(4*len
+1);
79 len
= strvis(name
, src
, flags
);
80 (void)printf("%s", name
);
84 errx(EXIT_FAILURE
, "out of memory!");
89 * The reasons why we don't use putwchar(wc) here are:
90 * - If wc == L'\0', we need to restore the initial shift state, but
91 * the C language standard doesn't say that putwchar(L'\0') does.
92 * - It isn't portable to mix a wide-oriented function (i.e. getwchar)
93 * with byte-oriented functions (printf et al.) in same FILE.
96 printwc(wchar_t wc
, mbstate_t *pst
)
101 size
= wcrtomb(buf
, wc
, pst
);
102 if (size
== (size_t)-1) /* This shouldn't happen, but for sure */
105 /* The following condition must be always true, but for sure */
106 if (size
> 0 && buf
[size
- 1] == '\0')
110 fwrite(buf
, 1, size
, stdout
);
111 return wc
== L
'\0' ? 0 : wcwidth(wc
);
115 printescaped(const char *src
)
118 mbstate_t src_state
, stdout_state
;
119 /* The following +1 is to pass '\0' at the end of src to mbrtowc(). */
120 const char *endptr
= src
+ strlen(src
) + 1;
123 * We have to reset src_state each time in this function, because
124 * the codeset of src pathname may not match with current locale.
125 * Note that if we pass NULL instead of src_state to mbrtowc(),
126 * there is no way to reset the state.
128 memset(&src_state
, 0, sizeof(src_state
));
129 memset(&stdout_state
, 0, sizeof(stdout_state
));
130 while (src
< endptr
) {
132 size_t rv
, span
= endptr
- src
;
136 * XXX - we should fix libc instead.
137 * Theoretically this should work, but our current
138 * implementation of iso2022 module doesn't actually work
139 * as expected, if there are redundant escape sequences
140 * which exceed 32 bytes.
142 if (span
> MB_CUR_MAX
)
145 rv
= mbrtowc(&wc
, src
, span
, &src_state
);
146 if (rv
== 0) { /* assert(wc == L'\0'); */
147 /* The following may output a shift sequence. */
148 n
+= printwc(wc
, &stdout_state
);
151 if (rv
== (size_t)-1) { /* probably errno == EILSEQ */
152 n
+= printwc(L
'?', &stdout_state
);
153 /* try to skip 1byte, because there is no better way */
155 memset(&src_state
, 0, sizeof(src_state
));
156 } else if (rv
== (size_t)-2) {
157 if (span
< MB_CUR_MAX
) { /* incomplete char */
158 n
+= printwc(L
'?', &stdout_state
);
161 src
+= span
; /* a redundant shift sequence? */
163 n
+= printwc(iswprint(wc
) ? wc
: L
'?', &stdout_state
);