conv.c revision 131954
16059Samurai/*
26059Samurai * Copyright (c) 1989, 1993
36059Samurai *	The Regents of the University of California.  All rights reserved.
46059Samurai *
56059Samurai * Redistribution and use in source and binary forms, with or without
66059Samurai * modification, are permitted provided that the following conditions
76059Samurai * are met:
86059Samurai * 1. Redistributions of source code must retain the above copyright
96059Samurai *    notice, this list of conditions and the following disclaimer.
106059Samurai * 2. Redistributions in binary form must reproduce the above copyright
116059Samurai *    notice, this list of conditions and the following disclaimer in the
126059Samurai *    documentation and/or other materials provided with the distribution.
136059Samurai * 3. All advertising materials mentioning features or use of this software
146059Samurai *    must display the following acknowledgement:
156059Samurai *	This product includes software developed by the University of
166059Samurai *	California, Berkeley and its contributors.
176059Samurai * 4. Neither the name of the University nor the names of its contributors
186059Samurai *    may be used to endorse or promote products derived from this software
198857Srgrimes *    without specific prior written permission.
208857Srgrimes *
218857Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
226059Samurai * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
236059Samurai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
246059Samurai * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
256059Samurai * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
266735Samurai * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
276059Samurai * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
286735Samurai * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
296735Samurai * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
306059Samurai * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
316059Samurai * SUCH DAMAGE.
326059Samurai */
336059Samurai
346735Samurai#ifndef lint
356735Samuraistatic const char sccsid[] = "@(#)conv.c	8.1 (Berkeley) 6/6/93";
366735Samurai#endif /* not lint */
376735Samurai#include <sys/cdefs.h>
386764Samurai__FBSDID("$FreeBSD: head/usr.bin/hexdump/conv.c 131954 2004-07-11 01:11:12Z tjr $");
396735Samurai
406764Samurai#include <sys/types.h>
416735Samurai
426735Samurai#include <assert.h>
436735Samurai#include <stdio.h>
446735Samurai#include <ctype.h>
456764Samurai#include <limits.h>
466735Samurai#include <stdlib.h>
476735Samurai#include <wchar.h>
486735Samurai#include <wctype.h>
496735Samurai#include "hexdump.h"
506735Samurai
516735Samuraivoid
526735Samuraiconv_c(PR *pr, u_char *p, size_t bufsize)
536735Samurai{
546735Samurai	char buf[10];
556735Samurai	char const *str;
566735Samurai	wchar_t wc;
576735Samurai	size_t clen, oclen;
586735Samurai	int converr, pad, width;
596735Samurai	char peekbuf[MB_LEN_MAX];
606735Samurai
616735Samurai	if (pr->mbleft > 0) {
626735Samurai		str = "**";
636735Samurai		pr->mbleft--;
646735Samurai		goto strpr;
656735Samurai	}
666735Samurai
676735Samurai	switch(*p) {
686735Samurai	case '\0':
696735Samurai		str = "\\0";
706735Samurai		goto strpr;
716735Samurai	/* case '\a': */
726735Samurai	case '\007':
736735Samurai		str = "\\a";
746735Samurai		goto strpr;
756735Samurai	case '\b':
766735Samurai		str = "\\b";
776735Samurai		goto strpr;
786735Samurai	case '\f':
796735Samurai		str = "\\f";
806735Samurai		goto strpr;
816735Samurai	case '\n':
826735Samurai		str = "\\n";
836059Samurai		goto strpr;
846059Samurai	case '\r':
856059Samurai		str = "\\r";
866059Samurai		goto strpr;
876059Samurai	case '\t':
886059Samurai		str = "\\t";
896059Samurai		goto strpr;
906059Samurai	case '\v':
916059Samurai		str = "\\v";
926059Samurai		goto strpr;
936059Samurai	default:
946059Samurai		break;
956059Samurai	}
966059Samurai	/*
976059Samurai	 * Multibyte characters are disabled for hexdump(1) for backwards
986059Samurai	 * compatibility and consistency (none of its other output formats
996059Samurai	 * recognize them correctly).
1006059Samurai	 */
1016059Samurai	converr = 0;
1026059Samurai	if (odmode && MB_CUR_MAX > 1) {
1036059Samurai		oclen = 0;
1046059Samurairetry:
1056059Samurai		clen = mbrtowc(&wc, p, bufsize, &pr->mbstate);
1066059Samurai		if (clen == 0)
1076059Samurai			clen = 1;
1086059Samurai		else if (clen == (size_t)-1 || (clen == (size_t)-2 &&
1096059Samurai		    buf == peekbuf)) {
1106059Samurai			memset(&pr->mbstate, 0, sizeof(pr->mbstate));
1116059Samurai			wc = *p;
1126059Samurai			clen = 1;
1136059Samurai			converr = 1;
1146059Samurai		} else if (clen == (size_t)-2) {
1156059Samurai			/*
1166059Samurai			 * Incomplete character; peek ahead and see if we
1176059Samurai			 * can complete it.
1186059Samurai			 */
1196059Samurai			oclen = bufsize;
1206059Samurai			bufsize = peek(p = peekbuf, MB_CUR_MAX);
1216059Samurai			goto retry;
1226059Samurai		}
1236059Samurai		clen += oclen;
1246059Samurai	} else {
1256059Samurai		wc = *p;
1266059Samurai		clen = 1;
1276059Samurai	}
1286059Samurai	if (!converr && iswprint(wc)) {
1296059Samurai		if (!odmode) {
1306059Samurai			*pr->cchar = 'c';
1316059Samurai			(void)printf(pr->fmt, (int)wc);
1326059Samurai		} else {
1336059Samurai			*pr->cchar = 'C';
1346059Samurai			assert(strcmp(pr->fmt, "%3C") == 0);
1356059Samurai			width = wcwidth(wc);
1366059Samurai			assert(width > 0);
1376059Samurai			pad = 3 - width;
1386059Samurai			if (pad < 0)
1396059Samurai				pad = 0;
1406059Samurai			(void)printf("%*s%C", pad, "", wc);
1416059Samurai			pr->mbleft = clen - 1;
1426059Samurai		}
1436059Samurai	} else {
1446059Samurai		(void)sprintf(buf, "%03o", (int)*p);
1456059Samurai		str = buf;
1466059Samuraistrpr:		*pr->cchar = 's';
1476059Samurai		(void)printf(pr->fmt, str);
1486059Samurai	}
1496059Samurai}
1506059Samurai
1516059Samuraivoid
1526059Samuraiconv_u(PR *pr, u_char *p)
1536059Samurai{
1546059Samurai	static char const * list[] = {
1556059Samurai		"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
1566059Samurai		 "bs",  "ht",  "lf",  "vt",  "ff",  "cr",  "so",  "si",
1576059Samurai		"dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb",
1586059Samurai		"can",  "em", "sub", "esc",  "fs",  "gs",  "rs",  "us",
1596059Samurai	};
1606059Samurai
1616059Samurai						/* od used nl, not lf */
1626059Samurai	if (*p <= 0x1f) {
1636059Samurai		*pr->cchar = 's';
1646059Samurai		if (odmode && *p == 0x0a)
1656735Samurai			(void)printf(pr->fmt, "nl");
1666735Samurai		else
1676735Samurai			(void)printf(pr->fmt, list[*p]);
1686735Samurai	} else if (*p == 0x7f) {
1696735Samurai		*pr->cchar = 's';
1706735Samurai		(void)printf(pr->fmt, "del");
1716735Samurai	} else if (odmode && *p == 0x20) {	/* od replaced space with sp */
1726735Samurai		*pr->cchar = 's';
1736735Samurai		(void)printf(pr->fmt, " sp");
1746735Samurai	} else if (isprint(*p)) {
1756735Samurai		*pr->cchar = 'c';
1766735Samurai		(void)printf(pr->fmt, *p);
1776735Samurai	} else {
1786735Samurai		*pr->cchar = 'x';
1796735Samurai		(void)printf(pr->fmt, (int)*p);
1806735Samurai	}
1816735Samurai}
1826735Samurai