addrutil: Re-indent.
[wk-misc.git] / undump.c
1 /* undump - Hex undump tool
2  * Copyright (C) 2000, 2010 Werner Koch (dd9jn)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  *
17  * 2010-09-02 wk  Changed to GPLv3.
18  *                Fixed detection of write errors.  Reported by Marcus
19  *                Brinkmann
20  * 2011-02-24 wk  Allow for 0x an \x prefixes.  Print offset with
21  *                the error messages.
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #define digitp(p)   ((p) >= '0' && (p) <= '9')
28 #define hexdigitp(a) (digitp (a)                     \
29                       || ((a) >= 'A' && (a) <= 'F')  \
30                       || ((a) >= 'a' && (a) <= 'f'))
31 #define ascii_isspace(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t')
32 #define xtoi_1(p)   ((p) <= '9'? ((p)- '0'): \
33                      (p) <= 'F'? ((p)-'A'+10):((p)-'a'+10))
34
35
36
37
38 int
39 main (int argc, char **argv )
40 {
41   int c1, c2;
42   unsigned int value;
43   unsigned long lnr, off;
44
45   if ( argc > 1 )
46     {
47       fprintf (stderr, "usage: undump < input\n");
48       return 1;
49     }
50
51
52   lnr = 1;
53   off = 0;
54   while ( (c1=getchar ()) != EOF )
55     {
56       off++;
57       if (c1 == '\n')
58         lnr++;
59       if (ascii_isspace (c1))
60         continue;
61       if (c1 == '\\')
62         {
63           /* Assume the hex digits are prefixed with \x.  */
64           c1 = getchar ();
65           off++;
66           if (c1 != EOF)
67             {
68               c2 = getchar ();
69               off++;
70             }
71           if (c1 != 'x' || c2 == EOF)
72             {
73               fprintf (stderr, "undump: incomplete \\x "
74                        "prefix at line %lu, off %lu\n", lnr, off);
75               return 1;
76             }
77           c1 = c2;
78         }
79       if (!hexdigitp (c1))
80         {
81           fprintf (stderr,
82                    "undump: non hex-digit encountered at line %lu, off %lu\n",
83                    lnr, off);
84           return 1;
85         }
86       if ( (c2=getchar ()) == EOF )
87         {
88           fprintf (stderr,
89                    "undump: error reading second nibble at line %lu, off %lu\n",
90                    lnr, off);
91           return 1;
92         }
93       off++;
94       if (c2 == '\n')
95         lnr++;
96       if (!hexdigitp (c2))
97         {
98           if (c1 == '0' && c2 == 'x')
99             {
100               /* Assume the hex digits are prefixed with 0x.  */
101               c1 = getchar ();
102               off++;
103               if (c1 != EOF)
104                 {
105                   c2 = getchar ();
106                   off++;
107                 }
108               if (c1 == EOF || c2 == EOF || !hexdigitp (c1) || !hexdigitp (c2))
109                 {
110                   fprintf (stderr, "undump: incomplete 0x "
111                            "prefix at line %lu, off %lu\n", lnr, off);
112                   return 1;
113                 }
114             }
115           else
116             {
117               fprintf (stderr, "undump: second nibble is not a hex-digit"
118                        " at line %lu, off %lu\n", lnr, off);
119               return 1;
120             }
121         }
122       value = xtoi_1 (c1) * 16 + xtoi_1 (c2);
123       putchar (value);
124     }
125   if (ferror (stdin))
126     {
127       fprintf (stderr, "undump: read error at line %lu, off %lu\n", lnr, off);
128       return 1;
129     }
130   if (ferror (stdout))
131     {
132       fprintf (stderr, "undump: write error at input line %lu, off %lu\n",
133                lnr, off);
134       return 1;
135     }
136
137   return 0;
138 }
139
140 /*
141 Local Variables:
142 compile-command: "cc -Wall -o undump undump.c"
143 End:
144 */