11590Srgrimes/*
21590Srgrimes * Copyright (c) 1989, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
301590Srgrimes#ifndef lint
3187203Smarkmstatic const char sccsid[] = "@(#)conv.c	8.1 (Berkeley) 6/6/93";
321590Srgrimes#endif /* not lint */
3391839Sobrien#include <sys/cdefs.h>
3491839Sobrien__FBSDID("$FreeBSD$");
351590Srgrimes
361590Srgrimes#include <sys/types.h>
371590Srgrimes
38131954Stjr#include <assert.h>
391590Srgrimes#include <ctype.h>
40131954Stjr#include <limits.h>
41132253Sjohan#include <stdio.h>
42131954Stjr#include <stdlib.h>
43132253Sjohan#include <string.h>
44131954Stjr#include <wchar.h>
45131954Stjr#include <wctype.h>
461590Srgrimes#include "hexdump.h"
471590Srgrimes
481590Srgrimesvoid
49131954Stjrconv_c(PR *pr, u_char *p, size_t bufsize)
501590Srgrimes{
5191839Sobrien	char buf[10];
5291839Sobrien	char const *str;
53131954Stjr	wchar_t wc;
54131954Stjr	size_t clen, oclen;
55131954Stjr	int converr, pad, width;
56228636Sdim	u_char peekbuf[MB_LEN_MAX];
571590Srgrimes
58131954Stjr	if (pr->mbleft > 0) {
59131954Stjr		str = "**";
60131954Stjr		pr->mbleft--;
61131954Stjr		goto strpr;
62131954Stjr	}
63131954Stjr
641590Srgrimes	switch(*p) {
651590Srgrimes	case '\0':
6691839Sobrien		str = "\\0";
671590Srgrimes		goto strpr;
681590Srgrimes	/* case '\a': */
691590Srgrimes	case '\007':
7091839Sobrien		str = "\\a";
711590Srgrimes		goto strpr;
721590Srgrimes	case '\b':
7391839Sobrien		str = "\\b";
741590Srgrimes		goto strpr;
751590Srgrimes	case '\f':
7691839Sobrien		str = "\\f";
771590Srgrimes		goto strpr;
781590Srgrimes	case '\n':
7991839Sobrien		str = "\\n";
801590Srgrimes		goto strpr;
811590Srgrimes	case '\r':
8291839Sobrien		str = "\\r";
831590Srgrimes		goto strpr;
841590Srgrimes	case '\t':
8591839Sobrien		str = "\\t";
861590Srgrimes		goto strpr;
871590Srgrimes	case '\v':
8891839Sobrien		str = "\\v";
891590Srgrimes		goto strpr;
901590Srgrimes	default:
911590Srgrimes		break;
921590Srgrimes	}
93131954Stjr	/*
94131954Stjr	 * Multibyte characters are disabled for hexdump(1) for backwards
95131954Stjr	 * compatibility and consistency (none of its other output formats
96131954Stjr	 * recognize them correctly).
97131954Stjr	 */
98131954Stjr	converr = 0;
99131954Stjr	if (odmode && MB_CUR_MAX > 1) {
100131954Stjr		oclen = 0;
101131954Stjrretry:
102131954Stjr		clen = mbrtowc(&wc, p, bufsize, &pr->mbstate);
103131954Stjr		if (clen == 0)
104131954Stjr			clen = 1;
105131954Stjr		else if (clen == (size_t)-1 || (clen == (size_t)-2 &&
106228636Sdim		    p == peekbuf)) {
107131954Stjr			memset(&pr->mbstate, 0, sizeof(pr->mbstate));
108131954Stjr			wc = *p;
109131954Stjr			clen = 1;
110131954Stjr			converr = 1;
111131954Stjr		} else if (clen == (size_t)-2) {
112131954Stjr			/*
113131954Stjr			 * Incomplete character; peek ahead and see if we
114131954Stjr			 * can complete it.
115131954Stjr			 */
116131954Stjr			oclen = bufsize;
117131954Stjr			bufsize = peek(p = peekbuf, MB_CUR_MAX);
118131954Stjr			goto retry;
119131954Stjr		}
120131954Stjr		clen += oclen;
1211590Srgrimes	} else {
122131954Stjr		wc = *p;
123131954Stjr		clen = 1;
124131954Stjr	}
125131954Stjr	if (!converr && iswprint(wc)) {
126131954Stjr		if (!odmode) {
127131954Stjr			*pr->cchar = 'c';
128131954Stjr			(void)printf(pr->fmt, (int)wc);
129131954Stjr		} else {
130131954Stjr			*pr->cchar = 'C';
131131954Stjr			assert(strcmp(pr->fmt, "%3C") == 0);
132131954Stjr			width = wcwidth(wc);
133160857Sjkoshy			assert(width >= 0);
134131954Stjr			pad = 3 - width;
135131954Stjr			if (pad < 0)
136131954Stjr				pad = 0;
137131954Stjr			(void)printf("%*s%C", pad, "", wc);
138131954Stjr			pr->mbleft = clen - 1;
139131954Stjr		}
140131954Stjr	} else {
14191839Sobrien		(void)sprintf(buf, "%03o", (int)*p);
14291839Sobrien		str = buf;
1431590Srgrimesstrpr:		*pr->cchar = 's';
1441590Srgrimes		(void)printf(pr->fmt, str);
1451590Srgrimes	}
1461590Srgrimes}
1471590Srgrimes
1481590Srgrimesvoid
149102944Sdwmaloneconv_u(PR *pr, u_char *p)
1501590Srgrimes{
15191839Sobrien	static char const * list[] = {
1521590Srgrimes		"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
1531590Srgrimes		 "bs",  "ht",  "lf",  "vt",  "ff",  "cr",  "so",  "si",
154247753Seadler		"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
1551590Srgrimes		"can",  "em", "sub", "esc",  "fs",  "gs",  "rs",  "us",
1561590Srgrimes	};
1571590Srgrimes
1581590Srgrimes						/* od used nl, not lf */
1591590Srgrimes	if (*p <= 0x1f) {
1601590Srgrimes		*pr->cchar = 's';
16196787Stjr		if (odmode && *p == 0x0a)
1621590Srgrimes			(void)printf(pr->fmt, "nl");
1631590Srgrimes		else
1641590Srgrimes			(void)printf(pr->fmt, list[*p]);
1651590Srgrimes	} else if (*p == 0x7f) {
1661590Srgrimes		*pr->cchar = 's';
1671590Srgrimes		(void)printf(pr->fmt, "del");
16896787Stjr	} else if (odmode && *p == 0x20) {	/* od replaced space with sp */
1691590Srgrimes		*pr->cchar = 's';
1701590Srgrimes		(void)printf(pr->fmt, " sp");
1711590Srgrimes	} else if (isprint(*p)) {
1721590Srgrimes		*pr->cchar = 'c';
1731590Srgrimes		(void)printf(pr->fmt, *p);
1741590Srgrimes	} else {
1751590Srgrimes		*pr->cchar = 'x';
1761590Srgrimes		(void)printf(pr->fmt, (int)*p);
1771590Srgrimes	}
1781590Srgrimes}
179