1*1e33498fSThomas Cort /* $NetBSD: odsyntax.c,v 1.28 2010/11/27 20:46:38 christos Exp $ */
2*1e33498fSThomas Cort
3*1e33498fSThomas Cort /*-
4*1e33498fSThomas Cort * Copyright (c) 1990, 1993
5*1e33498fSThomas Cort * The Regents of the University of California. All rights reserved.
6*1e33498fSThomas Cort *
7*1e33498fSThomas Cort * Redistribution and use in source and binary forms, with or without
8*1e33498fSThomas Cort * modification, are permitted provided that the following conditions
9*1e33498fSThomas Cort * are met:
10*1e33498fSThomas Cort * 1. Redistributions of source code must retain the above copyright
11*1e33498fSThomas Cort * notice, this list of conditions and the following disclaimer.
12*1e33498fSThomas Cort * 2. Redistributions in binary form must reproduce the above copyright
13*1e33498fSThomas Cort * notice, this list of conditions and the following disclaimer in the
14*1e33498fSThomas Cort * documentation and/or other materials provided with the distribution.
15*1e33498fSThomas Cort * 3. Neither the name of the University nor the names of its contributors
16*1e33498fSThomas Cort * may be used to endorse or promote products derived from this software
17*1e33498fSThomas Cort * without specific prior written permission.
18*1e33498fSThomas Cort *
19*1e33498fSThomas Cort * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*1e33498fSThomas Cort * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*1e33498fSThomas Cort * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*1e33498fSThomas Cort * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*1e33498fSThomas Cort * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*1e33498fSThomas Cort * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*1e33498fSThomas Cort * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*1e33498fSThomas Cort * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*1e33498fSThomas Cort * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*1e33498fSThomas Cort * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*1e33498fSThomas Cort * SUCH DAMAGE.
30*1e33498fSThomas Cort */
31*1e33498fSThomas Cort
32*1e33498fSThomas Cort #if HAVE_NBTOOL_CONFIG_H
33*1e33498fSThomas Cort #include "nbtool_config.h"
34*1e33498fSThomas Cort #endif
35*1e33498fSThomas Cort
36*1e33498fSThomas Cort #include <sys/cdefs.h>
37*1e33498fSThomas Cort #if !defined(lint)
38*1e33498fSThomas Cort #if 0
39*1e33498fSThomas Cort static char sccsid[] = "@(#)odsyntax.c 8.2 (Berkeley) 5/4/95";
40*1e33498fSThomas Cort #else
41*1e33498fSThomas Cort __RCSID("$NetBSD: odsyntax.c,v 1.28 2010/11/27 20:46:38 christos Exp $");
42*1e33498fSThomas Cort #endif
43*1e33498fSThomas Cort #endif /* not lint */
44*1e33498fSThomas Cort
45*1e33498fSThomas Cort #include <sys/types.h>
46*1e33498fSThomas Cort
47*1e33498fSThomas Cort #include <ctype.h>
48*1e33498fSThomas Cort #include <err.h>
49*1e33498fSThomas Cort #include <stdio.h>
50*1e33498fSThomas Cort #include <stdlib.h>
51*1e33498fSThomas Cort #include <unistd.h>
52*1e33498fSThomas Cort #include <util.h>
53*1e33498fSThomas Cort
54*1e33498fSThomas Cort #include "hexdump.h"
55*1e33498fSThomas Cort
56*1e33498fSThomas Cort #define PADDING " "
57*1e33498fSThomas Cort
58*1e33498fSThomas Cort struct odformat {
59*1e33498fSThomas Cort char type;
60*1e33498fSThomas Cort int nbytes;
61*1e33498fSThomas Cort char const *format;
62*1e33498fSThomas Cort int minwidth;
63*1e33498fSThomas Cort };
64*1e33498fSThomas Cort
65*1e33498fSThomas Cort struct odaddrformat {
66*1e33498fSThomas Cort char type;
67*1e33498fSThomas Cort char const *format1;
68*1e33498fSThomas Cort char const *format2;
69*1e33498fSThomas Cort };
70*1e33498fSThomas Cort
71*1e33498fSThomas Cort int odmode;
72*1e33498fSThomas Cort
73*1e33498fSThomas Cort static void odoffset(int, char ***);
74*1e33498fSThomas Cort static void posixtypes(char const *);
75*1e33498fSThomas Cort
76*1e33498fSThomas Cort void
odsyntax(int argc,char *** argvp)77*1e33498fSThomas Cort odsyntax(int argc, char ***argvp)
78*1e33498fSThomas Cort {
79*1e33498fSThomas Cort static char empty[] = "", padding[] = PADDING;
80*1e33498fSThomas Cort int ch;
81*1e33498fSThomas Cort char *p, **argv;
82*1e33498fSThomas Cort
83*1e33498fSThomas Cort #define TYPE_OFFSET 7
84*1e33498fSThomas Cort add("\"%07.7_Ao\n\"");
85*1e33498fSThomas Cort add("\"%07.7_ao \"");
86*1e33498fSThomas Cort
87*1e33498fSThomas Cort odmode = 1;
88*1e33498fSThomas Cort argv = *argvp;
89*1e33498fSThomas Cort while ((ch = getopt(argc, argv,
90*1e33498fSThomas Cort "A:aBbcDdeFfHhIij:LlN:Oot:vXx")) != -1)
91*1e33498fSThomas Cort switch (ch) {
92*1e33498fSThomas Cort case 'A':
93*1e33498fSThomas Cort switch (*optarg) {
94*1e33498fSThomas Cort case 'd': case 'o': case 'x':
95*1e33498fSThomas Cort fshead->nextfu->fmt[TYPE_OFFSET] = *optarg;
96*1e33498fSThomas Cort fshead->nextfs->nextfu->fmt[TYPE_OFFSET] =
97*1e33498fSThomas Cort *optarg;
98*1e33498fSThomas Cort break;
99*1e33498fSThomas Cort case 'n':
100*1e33498fSThomas Cort fshead->nextfu->fmt = empty;
101*1e33498fSThomas Cort fshead->nextfs->nextfu->fmt = padding;
102*1e33498fSThomas Cort break;
103*1e33498fSThomas Cort default:
104*1e33498fSThomas Cort errx(1, "%s: invalid address base", optarg);
105*1e33498fSThomas Cort }
106*1e33498fSThomas Cort break;
107*1e33498fSThomas Cort case 'a':
108*1e33498fSThomas Cort posixtypes("a");
109*1e33498fSThomas Cort break;
110*1e33498fSThomas Cort case 'B':
111*1e33498fSThomas Cort case 'o':
112*1e33498fSThomas Cort posixtypes("o2");
113*1e33498fSThomas Cort break;
114*1e33498fSThomas Cort case 'b':
115*1e33498fSThomas Cort posixtypes("o1");
116*1e33498fSThomas Cort break;
117*1e33498fSThomas Cort case 'c':
118*1e33498fSThomas Cort posixtypes("c");
119*1e33498fSThomas Cort break;
120*1e33498fSThomas Cort case 'd':
121*1e33498fSThomas Cort posixtypes("u2");
122*1e33498fSThomas Cort break;
123*1e33498fSThomas Cort case 'D':
124*1e33498fSThomas Cort posixtypes("u4");
125*1e33498fSThomas Cort break;
126*1e33498fSThomas Cort case 'e': /* undocumented in od */
127*1e33498fSThomas Cort case 'F':
128*1e33498fSThomas Cort posixtypes("f8");
129*1e33498fSThomas Cort break;
130*1e33498fSThomas Cort case 'f':
131*1e33498fSThomas Cort posixtypes("f4");
132*1e33498fSThomas Cort break;
133*1e33498fSThomas Cort case 'H':
134*1e33498fSThomas Cort case 'X':
135*1e33498fSThomas Cort posixtypes("x4");
136*1e33498fSThomas Cort break;
137*1e33498fSThomas Cort case 'h':
138*1e33498fSThomas Cort case 'x':
139*1e33498fSThomas Cort posixtypes("x2");
140*1e33498fSThomas Cort break;
141*1e33498fSThomas Cort case 'I':
142*1e33498fSThomas Cort case 'L':
143*1e33498fSThomas Cort case 'l':
144*1e33498fSThomas Cort posixtypes("d4");
145*1e33498fSThomas Cort break;
146*1e33498fSThomas Cort case 'i':
147*1e33498fSThomas Cort posixtypes("d2");
148*1e33498fSThomas Cort break;
149*1e33498fSThomas Cort case 'j':
150*1e33498fSThomas Cort if ((skip = strtol(optarg, &p, 0)) < 0)
151*1e33498fSThomas Cort errx(1, "%s: bad skip value", optarg);
152*1e33498fSThomas Cort switch(*p) {
153*1e33498fSThomas Cort case 'b':
154*1e33498fSThomas Cort skip *= 512;
155*1e33498fSThomas Cort break;
156*1e33498fSThomas Cort case 'k':
157*1e33498fSThomas Cort skip *= 1024;
158*1e33498fSThomas Cort break;
159*1e33498fSThomas Cort case 'm':
160*1e33498fSThomas Cort skip *= 1048576;
161*1e33498fSThomas Cort break;
162*1e33498fSThomas Cort }
163*1e33498fSThomas Cort break;
164*1e33498fSThomas Cort case 'N':
165*1e33498fSThomas Cort if ((length = atoi(optarg)) < 0)
166*1e33498fSThomas Cort errx(1, "%s: bad length value", optarg);
167*1e33498fSThomas Cort break;
168*1e33498fSThomas Cort case 'O':
169*1e33498fSThomas Cort posixtypes("o4");
170*1e33498fSThomas Cort break;
171*1e33498fSThomas Cort case 't':
172*1e33498fSThomas Cort posixtypes(optarg);
173*1e33498fSThomas Cort break;
174*1e33498fSThomas Cort case 'v':
175*1e33498fSThomas Cort vflag = ALL;
176*1e33498fSThomas Cort break;
177*1e33498fSThomas Cort case '?':
178*1e33498fSThomas Cort default:
179*1e33498fSThomas Cort usage();
180*1e33498fSThomas Cort }
181*1e33498fSThomas Cort
182*1e33498fSThomas Cort if (fshead->nextfs->nextfs == NULL)
183*1e33498fSThomas Cort posixtypes("oS");
184*1e33498fSThomas Cort
185*1e33498fSThomas Cort argc -= optind;
186*1e33498fSThomas Cort *argvp += optind;
187*1e33498fSThomas Cort
188*1e33498fSThomas Cort if (argc)
189*1e33498fSThomas Cort odoffset(argc, argvp);
190*1e33498fSThomas Cort }
191*1e33498fSThomas Cort
192*1e33498fSThomas Cort /* formats used for -t */
193*1e33498fSThomas Cort
194*1e33498fSThomas Cort static const struct odformat odftab[] = {
195*1e33498fSThomas Cort { 'a', 1, "%3_u", 4 },
196*1e33498fSThomas Cort { 'c', 1, "%3_c", 4 },
197*1e33498fSThomas Cort { 'd', 1, "%4d", 5 },
198*1e33498fSThomas Cort { 'd', 2, "%6d", 6 },
199*1e33498fSThomas Cort { 'd', 4, "%11d", 11 },
200*1e33498fSThomas Cort { 'd', 8, "%20d", 20 },
201*1e33498fSThomas Cort { 'o', 1, "%03o", 4 },
202*1e33498fSThomas Cort { 'o', 2, "%06o", 7 },
203*1e33498fSThomas Cort { 'o', 4, "%011o", 12 },
204*1e33498fSThomas Cort { 'o', 8, "%022o", 23 },
205*1e33498fSThomas Cort { 'u', 1, "%03u" , 4 },
206*1e33498fSThomas Cort { 'u', 2, "%05u" , 6 },
207*1e33498fSThomas Cort { 'u', 4, "%010u", 11 },
208*1e33498fSThomas Cort { 'u', 8, "%020u", 21 },
209*1e33498fSThomas Cort { 'x', 1, "%02x", 3 },
210*1e33498fSThomas Cort { 'x', 2, "%04x", 5 },
211*1e33498fSThomas Cort { 'x', 4, "%08x", 9 },
212*1e33498fSThomas Cort { 'x', 8, "%016x", 17 },
213*1e33498fSThomas Cort { 'f', 4, "%14.7e", 15 },
214*1e33498fSThomas Cort { 'f', 8, "%21.14e", 22 },
215*1e33498fSThomas Cort { 0, 0, NULL, 0 }
216*1e33498fSThomas Cort };
217*1e33498fSThomas Cort
218*1e33498fSThomas Cort /*
219*1e33498fSThomas Cort * Interpret a POSIX-style -t argument.
220*1e33498fSThomas Cort */
221*1e33498fSThomas Cort static void
posixtypes(char const * type_string)222*1e33498fSThomas Cort posixtypes(char const *type_string)
223*1e33498fSThomas Cort {
224*1e33498fSThomas Cort int nbytes = 0;
225*1e33498fSThomas Cort char *fmt, type, *tmp;
226*1e33498fSThomas Cort struct odformat const *odf;
227*1e33498fSThomas Cort
228*1e33498fSThomas Cort while (*type_string) {
229*1e33498fSThomas Cort switch ((type = *type_string++)) {
230*1e33498fSThomas Cort case 'a':
231*1e33498fSThomas Cort case 'c':
232*1e33498fSThomas Cort nbytes = 1;
233*1e33498fSThomas Cort break;
234*1e33498fSThomas Cort case 'f':
235*1e33498fSThomas Cort if (isupper((unsigned char)*type_string)) {
236*1e33498fSThomas Cort switch(*type_string) {
237*1e33498fSThomas Cort case 'F':
238*1e33498fSThomas Cort nbytes = sizeof(float);
239*1e33498fSThomas Cort break;
240*1e33498fSThomas Cort case 'D':
241*1e33498fSThomas Cort nbytes = sizeof(double);
242*1e33498fSThomas Cort break;
243*1e33498fSThomas Cort case 'L':
244*1e33498fSThomas Cort nbytes = sizeof(long double);
245*1e33498fSThomas Cort break;
246*1e33498fSThomas Cort default:
247*1e33498fSThomas Cort warnx("Bad type-size qualifier '%c'",
248*1e33498fSThomas Cort *type_string);
249*1e33498fSThomas Cort usage();
250*1e33498fSThomas Cort }
251*1e33498fSThomas Cort type_string++;
252*1e33498fSThomas Cort } else if (isdigit((unsigned char)*type_string)) {
253*1e33498fSThomas Cort nbytes = strtol(type_string, &tmp, 10);
254*1e33498fSThomas Cort type_string = tmp;
255*1e33498fSThomas Cort } else
256*1e33498fSThomas Cort nbytes = 8;
257*1e33498fSThomas Cort break;
258*1e33498fSThomas Cort case 'd':
259*1e33498fSThomas Cort case 'o':
260*1e33498fSThomas Cort case 'u':
261*1e33498fSThomas Cort case 'x':
262*1e33498fSThomas Cort if (isupper((unsigned char)*type_string)) {
263*1e33498fSThomas Cort switch(*type_string) {
264*1e33498fSThomas Cort case 'C':
265*1e33498fSThomas Cort nbytes = sizeof(char);
266*1e33498fSThomas Cort break;
267*1e33498fSThomas Cort case 'S':
268*1e33498fSThomas Cort nbytes = sizeof(short);
269*1e33498fSThomas Cort break;
270*1e33498fSThomas Cort case 'I':
271*1e33498fSThomas Cort nbytes = sizeof(int);
272*1e33498fSThomas Cort break;
273*1e33498fSThomas Cort case 'L':
274*1e33498fSThomas Cort nbytes = sizeof(long);
275*1e33498fSThomas Cort break;
276*1e33498fSThomas Cort default:
277*1e33498fSThomas Cort warnx("Bad type-size qualifier '%c'",
278*1e33498fSThomas Cort *type_string);
279*1e33498fSThomas Cort usage();
280*1e33498fSThomas Cort }
281*1e33498fSThomas Cort type_string++;
282*1e33498fSThomas Cort } else if (isdigit((unsigned char)*type_string)) {
283*1e33498fSThomas Cort nbytes = strtol(type_string, &tmp, 10);
284*1e33498fSThomas Cort type_string = tmp;
285*1e33498fSThomas Cort } else
286*1e33498fSThomas Cort nbytes = 4;
287*1e33498fSThomas Cort break;
288*1e33498fSThomas Cort default:
289*1e33498fSThomas Cort usage();
290*1e33498fSThomas Cort }
291*1e33498fSThomas Cort for (odf = odftab; odf->type != 0; odf++)
292*1e33498fSThomas Cort if (odf->type == type && odf->nbytes == nbytes)
293*1e33498fSThomas Cort break;
294*1e33498fSThomas Cort if (odf->type == 0)
295*1e33498fSThomas Cort errx(1, "%c%d: format not supported", type, nbytes);
296*1e33498fSThomas Cort (void)easprintf(&fmt, "%d/%d \"%*s%s \" \"\\n\"",
297*1e33498fSThomas Cort 16 / nbytes, nbytes,
298*1e33498fSThomas Cort 4 * nbytes - odf->minwidth, "", odf->format);
299*1e33498fSThomas Cort add(fmt);
300*1e33498fSThomas Cort }
301*1e33498fSThomas Cort }
302*1e33498fSThomas Cort
303*1e33498fSThomas Cort static void
odoffset(int argc,char *** argvp)304*1e33498fSThomas Cort odoffset(int argc, char ***argvp)
305*1e33498fSThomas Cort {
306*1e33498fSThomas Cort char *num, *p;
307*1e33498fSThomas Cort int base;
308*1e33498fSThomas Cort char *end;
309*1e33498fSThomas Cort
310*1e33498fSThomas Cort /*
311*1e33498fSThomas Cort * The offset syntax of od(1) was genuinely bizarre. First, if
312*1e33498fSThomas Cort * it started with a plus it had to be an offset. Otherwise, if
313*1e33498fSThomas Cort * there were at least two arguments, a number or lower-case 'x'
314*1e33498fSThomas Cort * followed by a number makes it an offset. By default it was
315*1e33498fSThomas Cort * octal; if it started with 'x' or '0x' it was hex. If it ended
316*1e33498fSThomas Cort * in a '.', it was decimal. If a 'b' or 'B' was appended, it
317*1e33498fSThomas Cort * multiplied the number by 512 or 1024 byte units. There was
318*1e33498fSThomas Cort * no way to assign a block count to a hex offset.
319*1e33498fSThomas Cort *
320*1e33498fSThomas Cort * We assume it's a file if the offset is bad.
321*1e33498fSThomas Cort */
322*1e33498fSThomas Cort p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
323*1e33498fSThomas Cort if (!p)
324*1e33498fSThomas Cort return;
325*1e33498fSThomas Cort
326*1e33498fSThomas Cort if (*p != '+' && (argc < 2 ||
327*1e33498fSThomas Cort (!isdigit((unsigned char)p[0]) &&
328*1e33498fSThomas Cort (p[0] != 'x' || !isxdigit((unsigned char)p[1])))))
329*1e33498fSThomas Cort return;
330*1e33498fSThomas Cort
331*1e33498fSThomas Cort base = 0;
332*1e33498fSThomas Cort /*
333*1e33498fSThomas Cort * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
334*1e33498fSThomas Cort * set base.
335*1e33498fSThomas Cort */
336*1e33498fSThomas Cort if (p[0] == '+')
337*1e33498fSThomas Cort ++p;
338*1e33498fSThomas Cort if (p[0] == 'x' && isxdigit((unsigned char)p[1])) {
339*1e33498fSThomas Cort ++p;
340*1e33498fSThomas Cort base = 16;
341*1e33498fSThomas Cort } else if (p[0] == '0' && p[1] == 'x') {
342*1e33498fSThomas Cort p += 2;
343*1e33498fSThomas Cort base = 16;
344*1e33498fSThomas Cort }
345*1e33498fSThomas Cort
346*1e33498fSThomas Cort /* skip over the number */
347*1e33498fSThomas Cort if (base == 16)
348*1e33498fSThomas Cort for (num = p; isxdigit((unsigned char)*p); ++p);
349*1e33498fSThomas Cort else
350*1e33498fSThomas Cort for (num = p; isdigit((unsigned char)*p); ++p);
351*1e33498fSThomas Cort
352*1e33498fSThomas Cort /* check for no number */
353*1e33498fSThomas Cort if (num == p)
354*1e33498fSThomas Cort return;
355*1e33498fSThomas Cort
356*1e33498fSThomas Cort /* if terminates with a '.', base is decimal */
357*1e33498fSThomas Cort if (*p == '.') {
358*1e33498fSThomas Cort if (base)
359*1e33498fSThomas Cort return;
360*1e33498fSThomas Cort base = 10;
361*1e33498fSThomas Cort }
362*1e33498fSThomas Cort
363*1e33498fSThomas Cort skip = strtol(num, &end, base ? base : 8);
364*1e33498fSThomas Cort
365*1e33498fSThomas Cort /* if end isn't the same as p, we got a non-octal digit */
366*1e33498fSThomas Cort if (end != p) {
367*1e33498fSThomas Cort skip = 0;
368*1e33498fSThomas Cort return;
369*1e33498fSThomas Cort }
370*1e33498fSThomas Cort
371*1e33498fSThomas Cort if (*p) {
372*1e33498fSThomas Cort if (*p == 'B') {
373*1e33498fSThomas Cort skip *= 1024;
374*1e33498fSThomas Cort ++p;
375*1e33498fSThomas Cort } else if (*p == 'b') {
376*1e33498fSThomas Cort skip *= 512;
377*1e33498fSThomas Cort ++p;
378*1e33498fSThomas Cort }
379*1e33498fSThomas Cort }
380*1e33498fSThomas Cort if (*p) {
381*1e33498fSThomas Cort skip = 0;
382*1e33498fSThomas Cort return;
383*1e33498fSThomas Cort }
384*1e33498fSThomas Cort /*
385*1e33498fSThomas Cort * If the offset uses a non-octal base, the base of the offset
386*1e33498fSThomas Cort * is changed as well. This isn't pretty, but it's easy.
387*1e33498fSThomas Cort */
388*1e33498fSThomas Cort if (base == 16) {
389*1e33498fSThomas Cort fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
390*1e33498fSThomas Cort fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
391*1e33498fSThomas Cort } else if (base == 10) {
392*1e33498fSThomas Cort fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
393*1e33498fSThomas Cort fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
394*1e33498fSThomas Cort }
395*1e33498fSThomas Cort
396*1e33498fSThomas Cort /* Terminate file list. */
397*1e33498fSThomas Cort (*argvp)[1] = NULL;
398*1e33498fSThomas Cort }
399