/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

  1. /*
  2. * Copyright (c) 1989, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 4. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #ifndef lint
  30. static const char sccsid[] = "@(#)conv.c 8.1 (Berkeley) 6/6/93";
  31. #endif /* not lint */
  32. #include <sys/cdefs.h>
  33. __FBSDID("$FreeBSD$");
  34. #include <sys/types.h>
  35. #include <assert.h>
  36. #include <ctype.h>
  37. #include <limits.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <wchar.h>
  42. #include <wctype.h>
  43. #include "hexdump.h"
  44. void
  45. conv_c(PR *pr, u_char *p, size_t bufsize)
  46. {
  47. char buf[10];
  48. char const *str;
  49. wchar_t wc;
  50. size_t clen, oclen;
  51. int converr, pad, width;
  52. u_char peekbuf[MB_LEN_MAX];
  53. if (pr->mbleft > 0) {
  54. str = "**";
  55. pr->mbleft--;
  56. goto strpr;
  57. }
  58. switch(*p) {
  59. case '\0':
  60. str = "\\0";
  61. goto strpr;
  62. /* case '\a': */
  63. case '\007':
  64. str = "\\a";
  65. goto strpr;
  66. case '\b':
  67. str = "\\b";
  68. goto strpr;
  69. case '\f':
  70. str = "\\f";
  71. goto strpr;
  72. case '\n':
  73. str = "\\n";
  74. goto strpr;
  75. case '\r':
  76. str = "\\r";
  77. goto strpr;
  78. case '\t':
  79. str = "\\t";
  80. goto strpr;
  81. case '\v':
  82. str = "\\v";
  83. goto strpr;
  84. default:
  85. break;
  86. }
  87. /*
  88. * Multibyte characters are disabled for hexdump(1) for backwards
  89. * compatibility and consistency (none of its other output formats
  90. * recognize them correctly).
  91. */
  92. converr = 0;
  93. if (odmode && MB_CUR_MAX > 1) {
  94. oclen = 0;
  95. retry:
  96. clen = mbrtowc(&wc, p, bufsize, &pr->mbstate);
  97. if (clen == 0)
  98. clen = 1;
  99. else if (clen == (size_t)-1 || (clen == (size_t)-2 &&
  100. p == peekbuf)) {
  101. memset(&pr->mbstate, 0, sizeof(pr->mbstate));
  102. wc = *p;
  103. clen = 1;
  104. converr = 1;
  105. } else if (clen == (size_t)-2) {
  106. /*
  107. * Incomplete character; peek ahead and see if we
  108. * can complete it.
  109. */
  110. oclen = bufsize;
  111. bufsize = peek(p = peekbuf, MB_CUR_MAX);
  112. goto retry;
  113. }
  114. clen += oclen;
  115. } else {
  116. wc = *p;
  117. clen = 1;
  118. }
  119. if (!converr && iswprint(wc)) {
  120. if (!odmode) {
  121. *pr->cchar = 'c';
  122. (void)printf(pr->fmt, (int)wc);
  123. } else {
  124. *pr->cchar = 'C';
  125. assert(strcmp(pr->fmt, "%3C") == 0);
  126. width = wcwidth(wc);
  127. assert(width >= 0);
  128. pad = 3 - width;
  129. if (pad < 0)
  130. pad = 0;
  131. (void)printf("%*s%C", pad, "", wc);
  132. pr->mbleft = clen - 1;
  133. }
  134. } else {
  135. (void)sprintf(buf, "%03o", (int)*p);
  136. str = buf;
  137. strpr: *pr->cchar = 's';
  138. (void)printf(pr->fmt, str);
  139. }
  140. }
  141. void
  142. conv_u(PR *pr, u_char *p)
  143. {
  144. static char const * list[] = {
  145. "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
  146. "bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
  147. "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb",
  148. "can", "em", "sub", "esc", "fs", "gs", "rs", "us",
  149. };
  150. /* od used nl, not lf */
  151. if (*p <= 0x1f) {
  152. *pr->cchar = 's';
  153. if (odmode && *p == 0x0a)
  154. (void)printf(pr->fmt, "nl");
  155. else
  156. (void)printf(pr->fmt, list[*p]);
  157. } else if (*p == 0x7f) {
  158. *pr->cchar = 's';
  159. (void)printf(pr->fmt, "del");
  160. } else if (odmode && *p == 0x20) { /* od replaced space with sp */
  161. *pr->cchar = 's';
  162. (void)printf(pr->fmt, " sp");
  163. } else if (isprint(*p)) {
  164. *pr->cchar = 'c';
  165. (void)printf(pr->fmt, *p);
  166. } else {
  167. *pr->cchar = 'x';
  168. (void)printf(pr->fmt, (int)*p);
  169. }
  170. }