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