/usr.bin/hexdump/conv.c
https://bitbucket.org/freebsd/freebsd-head/ · C · 178 lines · 131 code · 8 blank · 39 comment · 37 complexity · 8754e0dfc0498f64a25b5860109dce4f MD5 · raw file
- /*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #ifndef lint
- static const char sccsid[] = "@(#)conv.c 8.1 (Berkeley) 6/6/93";
- #endif /* not lint */
- #include <sys/cdefs.h>
- __FBSDID("$FreeBSD$");
- #include <sys/types.h>
- #include <assert.h>
- #include <ctype.h>
- #include <limits.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <wchar.h>
- #include <wctype.h>
- #include "hexdump.h"
- void
- conv_c(PR *pr, u_char *p, size_t bufsize)
- {
- char buf[10];
- char const *str;
- wchar_t wc;
- size_t clen, oclen;
- int converr, pad, width;
- u_char peekbuf[MB_LEN_MAX];
- if (pr->mbleft > 0) {
- str = "**";
- pr->mbleft--;
- goto strpr;
- }
- switch(*p) {
- case '\0':
- str = "\\0";
- goto strpr;
- /* case '\a': */
- case '\007':
- str = "\\a";
- goto strpr;
- case '\b':
- str = "\\b";
- goto strpr;
- case '\f':
- str = "\\f";
- goto strpr;
- case '\n':
- str = "\\n";
- goto strpr;
- case '\r':
- str = "\\r";
- goto strpr;
- case '\t':
- str = "\\t";
- goto strpr;
- case '\v':
- str = "\\v";
- goto strpr;
- default:
- break;
- }
- /*
- * Multibyte characters are disabled for hexdump(1) for backwards
- * compatibility and consistency (none of its other output formats
- * recognize them correctly).
- */
- converr = 0;
- if (odmode && MB_CUR_MAX > 1) {
- oclen = 0;
- retry:
- clen = mbrtowc(&wc, p, bufsize, &pr->mbstate);
- if (clen == 0)
- clen = 1;
- else if (clen == (size_t)-1 || (clen == (size_t)-2 &&
- p == peekbuf)) {
- memset(&pr->mbstate, 0, sizeof(pr->mbstate));
- wc = *p;
- clen = 1;
- converr = 1;
- } else if (clen == (size_t)-2) {
- /*
- * Incomplete character; peek ahead and see if we
- * can complete it.
- */
- oclen = bufsize;
- bufsize = peek(p = peekbuf, MB_CUR_MAX);
- goto retry;
- }
- clen += oclen;
- } else {
- wc = *p;
- clen = 1;
- }
- if (!converr && iswprint(wc)) {
- if (!odmode) {
- *pr->cchar = 'c';
- (void)printf(pr->fmt, (int)wc);
- } else {
- *pr->cchar = 'C';
- assert(strcmp(pr->fmt, "%3C") == 0);
- width = wcwidth(wc);
- assert(width >= 0);
- pad = 3 - width;
- if (pad < 0)
- pad = 0;
- (void)printf("%*s%C", pad, "", wc);
- pr->mbleft = clen - 1;
- }
- } else {
- (void)sprintf(buf, "%03o", (int)*p);
- str = buf;
- strpr: *pr->cchar = 's';
- (void)printf(pr->fmt, str);
- }
- }
- void
- conv_u(PR *pr, u_char *p)
- {
- static char const * list[] = {
- "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
- "bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
- "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb",
- "can", "em", "sub", "esc", "fs", "gs", "rs", "us",
- };
- /* od used nl, not lf */
- if (*p <= 0x1f) {
- *pr->cchar = 's';
- if (odmode && *p == 0x0a)
- (void)printf(pr->fmt, "nl");
- else
- (void)printf(pr->fmt, list[*p]);
- } else if (*p == 0x7f) {
- *pr->cchar = 's';
- (void)printf(pr->fmt, "del");
- } else if (odmode && *p == 0x20) { /* od replaced space with sp */
- *pr->cchar = 's';
- (void)printf(pr->fmt, " sp");
- } else if (isprint(*p)) {
- *pr->cchar = 'c';
- (void)printf(pr->fmt, *p);
- } else {
- *pr->cchar = 'x';
- (void)printf(pr->fmt, (int)*p);
- }
- }