xref: /freebsd/usr.bin/hexdump/conv.c (revision 40ccfb3137698ded12c4e40e953f337e6bb14cfa)
19b50d902SRodney W. Grimes /*
29b50d902SRodney W. Grimes  * Copyright (c) 1989, 1993
39b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
49b50d902SRodney W. Grimes  *
59b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
69b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
79b50d902SRodney W. Grimes  * are met:
89b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
99b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
109b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
119b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
129b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
139b50d902SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
149b50d902SRodney W. Grimes  *    must display the following acknowledgement:
159b50d902SRodney W. Grimes  *	This product includes software developed by the University of
169b50d902SRodney W. Grimes  *	California, Berkeley and its contributors.
179b50d902SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
189b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
199b50d902SRodney W. Grimes  *    without specific prior written permission.
209b50d902SRodney W. Grimes  *
219b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
229b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
249b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
259b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
269b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
279b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
289b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
299b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
309b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
319b50d902SRodney W. Grimes  * SUCH DAMAGE.
329b50d902SRodney W. Grimes  */
339b50d902SRodney W. Grimes 
349b50d902SRodney W. Grimes #ifndef lint
35c38cc743SMark Murray static const char sccsid[] = "@(#)conv.c	8.1 (Berkeley) 6/6/93";
369b50d902SRodney W. Grimes #endif /* not lint */
3795e5dc04SDavid E. O'Brien #include <sys/cdefs.h>
3895e5dc04SDavid E. O'Brien __FBSDID("$FreeBSD$");
399b50d902SRodney W. Grimes 
409b50d902SRodney W. Grimes #include <sys/types.h>
419b50d902SRodney W. Grimes 
4240ccfb31STim J. Robbins #include <assert.h>
439b50d902SRodney W. Grimes #include <stdio.h>
449b50d902SRodney W. Grimes #include <ctype.h>
4540ccfb31STim J. Robbins #include <limits.h>
4640ccfb31STim J. Robbins #include <stdlib.h>
4740ccfb31STim J. Robbins #include <wchar.h>
4840ccfb31STim J. Robbins #include <wctype.h>
499b50d902SRodney W. Grimes #include "hexdump.h"
509b50d902SRodney W. Grimes 
519b50d902SRodney W. Grimes void
5240ccfb31STim J. Robbins conv_c(PR *pr, u_char *p, size_t bufsize)
539b50d902SRodney W. Grimes {
5495e5dc04SDavid E. O'Brien 	char buf[10];
5595e5dc04SDavid E. O'Brien 	char const *str;
5640ccfb31STim J. Robbins 	wchar_t wc;
5740ccfb31STim J. Robbins 	size_t clen, oclen;
5840ccfb31STim J. Robbins 	int converr, pad, width;
5940ccfb31STim J. Robbins 	char peekbuf[MB_LEN_MAX];
6040ccfb31STim J. Robbins 
6140ccfb31STim J. Robbins 	if (pr->mbleft > 0) {
6240ccfb31STim J. Robbins 		str = "**";
6340ccfb31STim J. Robbins 		pr->mbleft--;
6440ccfb31STim J. Robbins 		goto strpr;
6540ccfb31STim J. Robbins 	}
669b50d902SRodney W. Grimes 
679b50d902SRodney W. Grimes 	switch(*p) {
689b50d902SRodney W. Grimes 	case '\0':
6995e5dc04SDavid E. O'Brien 		str = "\\0";
709b50d902SRodney W. Grimes 		goto strpr;
719b50d902SRodney W. Grimes 	/* case '\a': */
729b50d902SRodney W. Grimes 	case '\007':
7395e5dc04SDavid E. O'Brien 		str = "\\a";
749b50d902SRodney W. Grimes 		goto strpr;
759b50d902SRodney W. Grimes 	case '\b':
7695e5dc04SDavid E. O'Brien 		str = "\\b";
779b50d902SRodney W. Grimes 		goto strpr;
789b50d902SRodney W. Grimes 	case '\f':
7995e5dc04SDavid E. O'Brien 		str = "\\f";
809b50d902SRodney W. Grimes 		goto strpr;
819b50d902SRodney W. Grimes 	case '\n':
8295e5dc04SDavid E. O'Brien 		str = "\\n";
839b50d902SRodney W. Grimes 		goto strpr;
849b50d902SRodney W. Grimes 	case '\r':
8595e5dc04SDavid E. O'Brien 		str = "\\r";
869b50d902SRodney W. Grimes 		goto strpr;
879b50d902SRodney W. Grimes 	case '\t':
8895e5dc04SDavid E. O'Brien 		str = "\\t";
899b50d902SRodney W. Grimes 		goto strpr;
909b50d902SRodney W. Grimes 	case '\v':
9195e5dc04SDavid E. O'Brien 		str = "\\v";
929b50d902SRodney W. Grimes 		goto strpr;
939b50d902SRodney W. Grimes 	default:
949b50d902SRodney W. Grimes 		break;
959b50d902SRodney W. Grimes 	}
9640ccfb31STim J. Robbins 	/*
9740ccfb31STim J. Robbins 	 * Multibyte characters are disabled for hexdump(1) for backwards
9840ccfb31STim J. Robbins 	 * compatibility and consistency (none of its other output formats
9940ccfb31STim J. Robbins 	 * recognize them correctly).
10040ccfb31STim J. Robbins 	 */
10140ccfb31STim J. Robbins 	converr = 0;
10240ccfb31STim J. Robbins 	if (odmode && MB_CUR_MAX > 1) {
10340ccfb31STim J. Robbins 		oclen = 0;
10440ccfb31STim J. Robbins retry:
10540ccfb31STim J. Robbins 		clen = mbrtowc(&wc, p, bufsize, &pr->mbstate);
10640ccfb31STim J. Robbins 		if (clen == 0)
10740ccfb31STim J. Robbins 			clen = 1;
10840ccfb31STim J. Robbins 		else if (clen == (size_t)-1 || (clen == (size_t)-2 &&
10940ccfb31STim J. Robbins 		    buf == peekbuf)) {
11040ccfb31STim J. Robbins 			memset(&pr->mbstate, 0, sizeof(pr->mbstate));
11140ccfb31STim J. Robbins 			wc = *p;
11240ccfb31STim J. Robbins 			clen = 1;
11340ccfb31STim J. Robbins 			converr = 1;
11440ccfb31STim J. Robbins 		} else if (clen == (size_t)-2) {
11540ccfb31STim J. Robbins 			/*
11640ccfb31STim J. Robbins 			 * Incomplete character; peek ahead and see if we
11740ccfb31STim J. Robbins 			 * can complete it.
11840ccfb31STim J. Robbins 			 */
11940ccfb31STim J. Robbins 			oclen = bufsize;
12040ccfb31STim J. Robbins 			bufsize = peek(p = peekbuf, MB_CUR_MAX);
12140ccfb31STim J. Robbins 			goto retry;
12240ccfb31STim J. Robbins 		}
12340ccfb31STim J. Robbins 		clen += oclen;
12440ccfb31STim J. Robbins 	} else {
12540ccfb31STim J. Robbins 		wc = *p;
12640ccfb31STim J. Robbins 		clen = 1;
12740ccfb31STim J. Robbins 	}
12840ccfb31STim J. Robbins 	if (!converr && iswprint(wc)) {
12940ccfb31STim J. Robbins 		if (!odmode) {
1309b50d902SRodney W. Grimes 			*pr->cchar = 'c';
13140ccfb31STim J. Robbins 			(void)printf(pr->fmt, (int)wc);
13240ccfb31STim J. Robbins 		} else {
13340ccfb31STim J. Robbins 			*pr->cchar = 'C';
13440ccfb31STim J. Robbins 			assert(strcmp(pr->fmt, "%3C") == 0);
13540ccfb31STim J. Robbins 			width = wcwidth(wc);
13640ccfb31STim J. Robbins 			assert(width > 0);
13740ccfb31STim J. Robbins 			pad = 3 - width;
13840ccfb31STim J. Robbins 			if (pad < 0)
13940ccfb31STim J. Robbins 				pad = 0;
14040ccfb31STim J. Robbins 			(void)printf("%*s%C", pad, "", wc);
14140ccfb31STim J. Robbins 			pr->mbleft = clen - 1;
14240ccfb31STim J. Robbins 		}
1439b50d902SRodney W. Grimes 	} else {
14495e5dc04SDavid E. O'Brien 		(void)sprintf(buf, "%03o", (int)*p);
14595e5dc04SDavid E. O'Brien 		str = buf;
1469b50d902SRodney W. Grimes strpr:		*pr->cchar = 's';
1479b50d902SRodney W. Grimes 		(void)printf(pr->fmt, str);
1489b50d902SRodney W. Grimes 	}
1499b50d902SRodney W. Grimes }
1509b50d902SRodney W. Grimes 
1519b50d902SRodney W. Grimes void
152f4ac32deSDavid Malone conv_u(PR *pr, u_char *p)
1539b50d902SRodney W. Grimes {
15495e5dc04SDavid E. O'Brien 	static char const * list[] = {
1559b50d902SRodney W. Grimes 		"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
1569b50d902SRodney W. Grimes 		 "bs",  "ht",  "lf",  "vt",  "ff",  "cr",  "so",  "si",
1579b50d902SRodney W. Grimes 		"dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb",
1589b50d902SRodney W. Grimes 		"can",  "em", "sub", "esc",  "fs",  "gs",  "rs",  "us",
1599b50d902SRodney W. Grimes 	};
1609b50d902SRodney W. Grimes 
1619b50d902SRodney W. Grimes 						/* od used nl, not lf */
1629b50d902SRodney W. Grimes 	if (*p <= 0x1f) {
1639b50d902SRodney W. Grimes 		*pr->cchar = 's';
164ca9cbcecSTim J. Robbins 		if (odmode && *p == 0x0a)
1659b50d902SRodney W. Grimes 			(void)printf(pr->fmt, "nl");
1669b50d902SRodney W. Grimes 		else
1679b50d902SRodney W. Grimes 			(void)printf(pr->fmt, list[*p]);
1689b50d902SRodney W. Grimes 	} else if (*p == 0x7f) {
1699b50d902SRodney W. Grimes 		*pr->cchar = 's';
1709b50d902SRodney W. Grimes 		(void)printf(pr->fmt, "del");
171ca9cbcecSTim J. Robbins 	} else if (odmode && *p == 0x20) {	/* od replaced space with sp */
1729b50d902SRodney W. Grimes 		*pr->cchar = 's';
1739b50d902SRodney W. Grimes 		(void)printf(pr->fmt, " sp");
1749b50d902SRodney W. Grimes 	} else if (isprint(*p)) {
1759b50d902SRodney W. Grimes 		*pr->cchar = 'c';
1769b50d902SRodney W. Grimes 		(void)printf(pr->fmt, *p);
1779b50d902SRodney W. Grimes 	} else {
1789b50d902SRodney W. Grimes 		*pr->cchar = 'x';
1799b50d902SRodney W. Grimes 		(void)printf(pr->fmt, (int)*p);
1809b50d902SRodney W. Grimes 	}
1819b50d902SRodney W. Grimes }
182