1 /*
2 * Copyright (c) 2019,2020 Linaro Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <ctype.h>
8 #include <stdio.h>
9 #include "util_sformat.h"
10
sf_hex_ascii(unsigned char * data,size_t len,unsigned char nonvis)11 static void sf_hex_ascii(unsigned char *data, size_t len, unsigned char nonvis)
12 {
13 uint32_t idx;
14
15 /* Render printable characters. */
16 idx = 0;
17 while (len) {
18 printf("%c", isprint(data[idx]) ? data[idx] : nonvis);
19 idx++;
20 len--;
21 }
22 }
23
sf_hex_tabulate_16(struct sf_hex_tbl_fmt * fmt,unsigned char * data,size_t len)24 void sf_hex_tabulate_16(struct sf_hex_tbl_fmt *fmt, unsigned char *data,
25 size_t len)
26 {
27 uint32_t idx;
28 uint32_t cpos; /* Current position. */
29 uint32_t ca; /* Current address. */
30 uint32_t ea; /* End address. */
31
32 if (!len) {
33 return;
34 }
35
36 /* Set the end address (since we modify len in the write loop). */
37 ea = fmt->addr + len;
38
39 /* Check if we need to render the top address bar. */
40 if (fmt->addr_label) {
41 /* Render the top address bar. */
42 printf("\n");
43 printf(" ");
44 printf("0 1 2 3 4 5 6 7 8 9 ");
45 printf("A B C D E F\n");
46 printf("%08X ", fmt->addr - (fmt->addr % 16));
47 }
48
49 /* Insert offset padding for first row if necessary. */
50 cpos = fmt->addr % 16;
51 if (cpos != 0) {
52 for (idx = 0; idx < cpos; idx++) {
53 printf(" ");
54 }
55 }
56
57 /* Print data row by row. */
58 idx = 0;
59 ca = fmt->addr;
60 while (len) {
61 /* Print the current value. */
62 printf("%02X ", data[idx++]);
63 cpos++;
64 ca++;
65
66 /* Wrap around to the next line if necessary. */
67 if (cpos == 16 || ca == ea) {
68 /* Render ASCII equiv at end of row if requested. */
69 if (fmt->ascii) {
70 if (ca == ea) {
71 /* Handle last/single row. */
72 if (ca % 16) {
73 /* PARTIAL row (< 16 vals). */
74 printf("%.*s",
75 (16 - ca % 16) * 3,
76 " "
77 " "
78 " ");
79 sf_hex_ascii(
80 &data[idx - (ca % 16)],
81 ca - fmt->addr < 16 ?
82 idx % 16 : ca % 16,
83 '.');
84 } else {
85 /* FULL row. */
86 sf_hex_ascii(
87 &data[idx - 16],
88 16, '.');
89 }
90 } else if (ca < fmt->addr + 15) {
91 /* Handle first row. */
92 printf("%.*s", fmt->addr % 16,
93 " ");
94 sf_hex_ascii(data,
95 16 - fmt->addr % 16, '.');
96 } else {
97 /* Full row. */
98 sf_hex_ascii(&data[idx - 16], 16, '.');
99 }
100 }
101
102 /* Wrap around if this isn't the last row. */
103 printf("\n");
104 if (ca != ea) {
105 /* Render the next base row addr. */
106 if (fmt->addr_label) {
107 printf("%08X ", ca);
108 }
109 }
110 cpos = 0;
111 }
112 len--;
113 }
114 printf("\n");
115 }
116