51 broke -E logic completely, rewise it
[tfcrypt.git] / mhexdump.c
1 /*
2  * tfcrypt -- high security Threefish encryption tool.
3  *
4  * tfcrypt is copyrighted:
5  * Copyright (C) 2012-2019 Andrey Rys. All rights reserved.
6  *
7  * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <stdint.h>
35
36 #undef MACHINE_16BIT
37 #undef MACHINE_32BIT
38 #undef MACHINE_64BIT
39
40 #if UINTPTR_MAX == UINT32_MAX
41 #define MACHINE_32BIT
42 #elif UINTPTR_MAX == UINT64_MAX
43 #define MACHINE_64BIT
44 #elif UINTPTR_MAX == UINT16_MAX
45 #define MACHINE_16BIT
46 #endif
47
48 struct mhexdump_args {
49         const void *data;
50         size_t szdata;
51         int group;
52         int hexgroup;
53         int hexstr;
54         int addaddr;
55         int newline;
56         FILE *fp;
57         int closef;
58 };
59
60 #if defined(MACHINE_32BIT)
61 #define ADDRFMT "%08x: "
62 #define paddr (mha->addaddr == 2 ? (uint32_t)P+(x*mha->group) : (x*mha->group))
63 #elif defined(MACHINE_64BIT)
64 #define ADDRFMT "%016lx: "
65 #define paddr (mha->addaddr == 2 ? (uint64_t)P+(x*mha->group) : (x*mha->group))
66 #elif defined(MACHINE_16BIT)
67 #define ADDRFMT "%04x: "
68 #define paddr (mha->addaddr == 2 ? (uint16_t)P+(x*mha->group) : (x*mha->group))
69 #else
70 #error No machine word size detected!
71 #endif
72
73 #define BYTEOUT ((unsigned char)P[y+(x*mha->group)])
74
75 int fmhexdump(const struct mhexdump_args *mha)
76 {
77         const unsigned char *P = mha->data;
78         int x, y;
79
80         if (!mha->fp || !mha->data || mha->szdata == 0) return 0;
81
82         for (x = 0; x < mha->szdata/mha->group; x++) {
83                 if (mha->addaddr) fprintf(mha->fp, ADDRFMT, paddr);
84                 for (y = 0; y < mha->group; y++) {
85                         fprintf(mha->fp, "%02hhx", BYTEOUT);
86                         if (((y+1) % mha->hexgroup) == 0 && (y != (mha->group)-1)) fputc(' ', mha->fp);
87                 }
88                 if (mha->hexstr) fprintf(mha->fp, "  ");
89                 if (mha->hexstr) for (y = 0; y < mha->group; y++) {
90                         if (isprint(BYTEOUT)) fprintf(mha->fp, "%c", BYTEOUT);
91                         else fputc('.', mha->fp);
92                 }
93                 if (mha->szdata/mha->group == 1 && mha->szdata-mha->group == 0) {
94                         if (mha->newline) fputc('\n', mha->fp);
95                 }
96                 else fputc('\n', mha->fp);
97         }
98         if (mha->szdata-(x*mha->group) == 0) goto _ret;
99
100         if (mha->addaddr) fprintf(mha->fp, ADDRFMT, paddr);
101         for (y = 0; y < mha->szdata-(x*mha->group); y++) {
102                 fprintf(mha->fp, "%02hhx", BYTEOUT);
103                 if (((y+1) % mha->hexgroup) == 0) fputc(' ', mha->fp);
104         }
105         if (mha->hexstr) for (; y < mha->group; y++) {
106                 fprintf(mha->fp, "  ");
107                 if (((y+1) % mha->hexgroup) == 0 && (y != mha->group-1)) fputc(' ', mha->fp);
108         }
109         if (mha->hexstr) fprintf(mha->fp, "  ");
110         if (mha->hexstr) for (y = 0; y < mha->szdata-(x*mha->group); y++) {
111                 if (isprint(BYTEOUT)) fprintf(mha->fp, "%c", BYTEOUT);
112                 else fputc('.', mha->fp);
113         }
114
115         if (mha->newline) fputc('\n', mha->fp);
116
117 _ret:   fflush(mha->fp);
118         if (mha->closef) fclose(mha->fp);
119         return 1;
120 }
121
122 #undef BYTEOUT
123
124 int xmhexdump(int to, const void *data, size_t szdata, int hgroup, int hexstr, int newline)
125 {
126         struct mhexdump_args mha;
127
128         if (hgroup == 0) hgroup = 16;
129
130         memset(&mha, 0, sizeof(struct mhexdump_args));
131         mha.fp = (to == 2) ? stderr : stdout;
132         mha.closef = 0;
133         mha.data = data;
134         mha.szdata = szdata;
135         mha.group = hgroup;
136         mha.hexgroup = hgroup;
137         mha.hexstr = hexstr;
138         mha.addaddr = 0;
139         mha.newline = newline;
140
141         return fmhexdump(&mha);
142 }