1*48a8138eStedu /* $OpenBSD: odsyntax.c,v 1.28 2017/05/30 05:58:44 tedu Exp $ */
27baf058cSpvalchev /* $NetBSD: odsyntax.c,v 1.15 2001/12/07 15:14:29 bjh21 Exp $ */
31258a77dSderaadt
4df930be7Sderaadt /*-
57baf058cSpvalchev * Copyright (c) 1990, 1993
67baf058cSpvalchev * The Regents of the University of California. All rights reserved.
7df930be7Sderaadt *
8df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt * modification, are permitted provided that the following conditions
10df930be7Sderaadt * are met:
11df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt * documentation and/or other materials provided with the distribution.
16f75387cbSmillert * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt * may be used to endorse or promote products derived from this software
18df930be7Sderaadt * without specific prior written permission.
19df930be7Sderaadt *
20df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt * SUCH DAMAGE.
31df930be7Sderaadt */
32df930be7Sderaadt
33df930be7Sderaadt #include <sys/types.h>
347baf058cSpvalchev
35baf68b34Smickey #include <ctype.h>
36baf68b34Smickey #include <err.h>
377baf058cSpvalchev #include <stdio.h>
387baf058cSpvalchev #include <stdlib.h>
397baf058cSpvalchev #include <unistd.h>
407baf058cSpvalchev
41df930be7Sderaadt #include "hexdump.h"
42df930be7Sderaadt
438d1ceb6eSfgsch #define PADDING " "
448d1ceb6eSfgsch
458cfaf194Ssobrado int odmode;
46df930be7Sderaadt
478d1ceb6eSfgsch static void odadd(const char *);
489844ea72Smmcc static void odoffset(int, char ***);
499844ea72Smmcc static __dead void oldusage(void);
509844ea72Smmcc static void posixtypes(char *);
517baf058cSpvalchev
527baf058cSpvalchev /*
537baf058cSpvalchev * formats used for -t
547baf058cSpvalchev */
557baf058cSpvalchev static const char *fmt[4][4] = {
567baf058cSpvalchev {
577baf058cSpvalchev "16/1 \"%3d \" \"\\n\"",
587baf058cSpvalchev "8/2 \" %05d \" \"\\n\"",
597baf058cSpvalchev "4/4 \" %010d \" \"\\n\"",
607baf058cSpvalchev "2/8 \" %019d \" \"\\n\""
617baf058cSpvalchev }, {
627baf058cSpvalchev "16/1 \"%03o \" \"\\n\"",
637baf058cSpvalchev "8/2 \" %06o \" \"\\n\"",
647baf058cSpvalchev "4/4 \" %011o\" \"\\n\"",
657baf058cSpvalchev "2/8 \" %022o \" \"\\n\""
667baf058cSpvalchev }, {
677baf058cSpvalchev "16/1 \"%03u \" \"\\n\"",
687baf058cSpvalchev "8/2 \" %05u \" \"\\n\"",
697baf058cSpvalchev "4/4 \" %010u \" \"\\n\"",
707baf058cSpvalchev "2/8 \" %020u \" \"\\n\""
717baf058cSpvalchev }, {
727baf058cSpvalchev "16/1 \" %02x \" \"\\n\"",
737baf058cSpvalchev "8/2 \" %04x \" \"\\n\"",
747baf058cSpvalchev "4/4 \" %08x \" \"\\n\"",
757baf058cSpvalchev "2/8 \" %16x \" \"\\n\""
767baf058cSpvalchev }
777baf058cSpvalchev };
787baf058cSpvalchev
79fe59d1d2Spvalchev void
oldsyntax(int argc,char *** argvp)803921aef3Sderaadt oldsyntax(int argc, char ***argvp)
81df930be7Sderaadt {
828d1ceb6eSfgsch static char empty[] = "", padding[] = PADDING;
83df930be7Sderaadt int ch;
847baf058cSpvalchev char *p, **argv;
85df930be7Sderaadt
868d1ceb6eSfgsch #define TYPE_OFFSET 7
878d1ceb6eSfgsch add("\"%07.7_Ao\n\"");
888d1ceb6eSfgsch add("\"%07.7_ao \"");
898d1ceb6eSfgsch
908cfaf194Ssobrado odmode = 1;
91df930be7Sderaadt argv = *argvp;
927baf058cSpvalchev while ((ch = getopt(argc, argv,
932c7625d7Ssobrado "A:aBbcDdeFfHhIij:LlN:Oost:vXx")) != -1)
94df930be7Sderaadt switch (ch) {
958d1ceb6eSfgsch case 'A':
968d1ceb6eSfgsch switch (*optarg) {
978d1ceb6eSfgsch case 'd': case 'o': case 'x':
988d1ceb6eSfgsch fshead->nextfu->fmt[TYPE_OFFSET] = *optarg;
998d1ceb6eSfgsch fshead->nextfs->nextfu->fmt[TYPE_OFFSET] =
1008d1ceb6eSfgsch *optarg;
1018d1ceb6eSfgsch break;
1028d1ceb6eSfgsch case 'n':
1038d1ceb6eSfgsch fshead->nextfu->fmt = empty;
1048d1ceb6eSfgsch fshead->nextfs->nextfu->fmt = padding;
1058d1ceb6eSfgsch break;
1068d1ceb6eSfgsch default:
1078d1ceb6eSfgsch errx(1, "%s: invalid address base", optarg);
1088d1ceb6eSfgsch }
1098d1ceb6eSfgsch break;
110df930be7Sderaadt case 'a':
1118d1ceb6eSfgsch odadd("16/1 \"%3_u \" \"\\n\"");
112df930be7Sderaadt break;
113df930be7Sderaadt case 'B':
114df930be7Sderaadt case 'o':
1158d1ceb6eSfgsch odadd("8/2 \" %06o \" \"\\n\"");
116df930be7Sderaadt break;
117df930be7Sderaadt case 'b':
1188d1ceb6eSfgsch odadd("16/1 \"%03o \" \"\\n\"");
119df930be7Sderaadt break;
120df930be7Sderaadt case 'c':
1218d1ceb6eSfgsch odadd("16/1 \"%3_c \" \"\\n\"");
122df930be7Sderaadt break;
123df930be7Sderaadt case 'd':
1248d1ceb6eSfgsch odadd("8/2 \" %05u \" \"\\n\"");
125df930be7Sderaadt break;
126df930be7Sderaadt case 'D':
1278d1ceb6eSfgsch odadd("4/4 \" %010u \" \"\\n\"");
128df930be7Sderaadt break;
1290ddef2cdSjmc case 'e':
130df930be7Sderaadt case 'F':
1318d1ceb6eSfgsch odadd("2/8 \" %21.14e \" \"\\n\"");
132df930be7Sderaadt break;
133df930be7Sderaadt case 'f':
1348d1ceb6eSfgsch odadd("4/4 \" %14.7e \" \"\\n\"");
135df930be7Sderaadt break;
136df930be7Sderaadt case 'H':
137df930be7Sderaadt case 'X':
1388d1ceb6eSfgsch odadd("4/4 \" %08x \" \"\\n\"");
139df930be7Sderaadt break;
140df930be7Sderaadt case 'h':
141df930be7Sderaadt case 'x':
1428d1ceb6eSfgsch odadd("8/2 \" %04x \" \"\\n\"");
143df930be7Sderaadt break;
144df930be7Sderaadt case 'I':
145df930be7Sderaadt case 'L':
146df930be7Sderaadt case 'l':
1478d1ceb6eSfgsch odadd("4/4 \" %11d \" \"\\n\"");
148df930be7Sderaadt break;
149df930be7Sderaadt case 'i':
1508d1ceb6eSfgsch odadd("8/2 \" %6d \" \"\\n\"");
151df930be7Sderaadt break;
1527baf058cSpvalchev case 'j':
1537baf058cSpvalchev if ((skip = strtol(optarg, &p, 0)) < 0)
1547baf058cSpvalchev errx(1, "%s: bad skip value", optarg);
1557baf058cSpvalchev switch(*p) {
1567baf058cSpvalchev case 'b':
1577baf058cSpvalchev skip *= 512;
1587baf058cSpvalchev break;
1597baf058cSpvalchev case 'k':
1607baf058cSpvalchev skip *= 1024;
1617baf058cSpvalchev break;
1627baf058cSpvalchev case 'm':
1637baf058cSpvalchev skip *= 1048576;
1647baf058cSpvalchev break;
1657baf058cSpvalchev }
1667baf058cSpvalchev break;
1677baf058cSpvalchev case 'N':
1687baf058cSpvalchev if ((length = atoi(optarg)) < 0)
1697baf058cSpvalchev errx(1, "%s: bad length value", optarg);
1707baf058cSpvalchev break;
171df930be7Sderaadt case 'O':
1728d1ceb6eSfgsch odadd("4/4 \" %011o \" \"\\n\"");
173df930be7Sderaadt break;
1742c7625d7Ssobrado case 's':
1752c7625d7Ssobrado odadd("8/2 \" %05d \" \"\\n\"");
1762c7625d7Ssobrado break;
1777baf058cSpvalchev case 't':
1787baf058cSpvalchev posixtypes(optarg);
1797baf058cSpvalchev break;
180df930be7Sderaadt case 'v':
181df930be7Sderaadt vflag = ALL;
182df930be7Sderaadt break;
183df930be7Sderaadt default:
1844bfbe945Smillert oldusage();
185df930be7Sderaadt }
186df930be7Sderaadt
1878d1ceb6eSfgsch if (fshead->nextfs->nextfs == NULL)
1888d1ceb6eSfgsch odadd(" 8/2 \"%06o \" \"\\n\"");
189df930be7Sderaadt
190df930be7Sderaadt argc -= optind;
191df930be7Sderaadt *argvp += optind;
192df930be7Sderaadt
1937baf058cSpvalchev if (argc)
194df930be7Sderaadt odoffset(argc, argvp);
195df930be7Sderaadt }
196df930be7Sderaadt
1977baf058cSpvalchev /*
1987baf058cSpvalchev * Interpret a POSIX-style -t argument.
1997baf058cSpvalchev */
2007baf058cSpvalchev static void
posixtypes(char * type_string)2013921aef3Sderaadt posixtypes(char *type_string)
2027baf058cSpvalchev {
2037baf058cSpvalchev int x, y, nbytes;
204df930be7Sderaadt
2057baf058cSpvalchev while (*type_string) {
2067baf058cSpvalchev switch (*type_string) {
2077baf058cSpvalchev case 'a':
2087baf058cSpvalchev type_string++;
2098d1ceb6eSfgsch odadd("16/1 \"%3_u \" \"\\n\"");
2107baf058cSpvalchev break;
2117baf058cSpvalchev case 'c':
2127baf058cSpvalchev type_string++;
2138d1ceb6eSfgsch odadd("16/1 \"%3_c \" \"\\n\"");
2147baf058cSpvalchev break;
2157baf058cSpvalchev case 'f':
2167baf058cSpvalchev type_string++;
2177baf058cSpvalchev if (*type_string == 'F' ||
2187baf058cSpvalchev *type_string == '4') {
2197baf058cSpvalchev type_string++;
2208d1ceb6eSfgsch odadd("4/4 \" %14.7e\" \"\\n\"");
2217baf058cSpvalchev } else if (*type_string == 'L' ||
2227baf058cSpvalchev *type_string == '8') {
2237baf058cSpvalchev type_string++;
2248d1ceb6eSfgsch odadd("2/8 \" %16.14e\" \"\\n\"");
2257baf058cSpvalchev } else if (*type_string == 'D')
2267baf058cSpvalchev /* long doubles vary in size */
2274bfbe945Smillert oldusage();
2287baf058cSpvalchev else
2298d1ceb6eSfgsch odadd("2/8 \" %16.14e\" \"\\n\"");
2307baf058cSpvalchev break;
2317baf058cSpvalchev case 'd':
2327baf058cSpvalchev x = 0;
2337baf058cSpvalchev goto extensions;
2347baf058cSpvalchev case 'o':
2357baf058cSpvalchev x = 1;
2367baf058cSpvalchev goto extensions;
2377baf058cSpvalchev case 'u':
2387baf058cSpvalchev x = 2;
2397baf058cSpvalchev goto extensions;
2407baf058cSpvalchev case 'x':
2417baf058cSpvalchev x = 3;
2427baf058cSpvalchev extensions:
2437baf058cSpvalchev type_string++;
2447baf058cSpvalchev y = 2;
245bd92c1fcSderaadt if (isupper((unsigned char)*type_string)) {
2467baf058cSpvalchev switch(*type_string) {
2477baf058cSpvalchev case 'C':
2487baf058cSpvalchev nbytes = sizeof(char);
2497baf058cSpvalchev break;
2507baf058cSpvalchev case 'S':
2517baf058cSpvalchev nbytes = sizeof(short);
2527baf058cSpvalchev break;
2537baf058cSpvalchev case 'I':
2547baf058cSpvalchev nbytes = sizeof(int);
2557baf058cSpvalchev break;
2567baf058cSpvalchev case 'L':
2577baf058cSpvalchev nbytes = sizeof(long);
2587baf058cSpvalchev break;
2597baf058cSpvalchev default:
2607baf058cSpvalchev warnx("Bad type-size qualifier '%c'",
2617baf058cSpvalchev *type_string);
2624bfbe945Smillert oldusage();
2637baf058cSpvalchev }
2647baf058cSpvalchev type_string++;
265bd92c1fcSderaadt } else if (isdigit((unsigned char)*type_string))
2667baf058cSpvalchev nbytes = strtol(type_string, &type_string, 10);
267afc75e31Snicm else
268afc75e31Snicm nbytes = 4;
2697baf058cSpvalchev
2707baf058cSpvalchev switch (nbytes) {
2717baf058cSpvalchev case 1:
2727baf058cSpvalchev y = 0;
2737baf058cSpvalchev break;
2747baf058cSpvalchev case 2:
2757baf058cSpvalchev y = 1;
2767baf058cSpvalchev break;
2777baf058cSpvalchev case 4:
2787baf058cSpvalchev y = 2;
2797baf058cSpvalchev break;
2807baf058cSpvalchev case 8:
2817baf058cSpvalchev y = 3;
2827baf058cSpvalchev break;
2837baf058cSpvalchev default:
2847baf058cSpvalchev warnx("%d-byte integer formats are not "
2857baf058cSpvalchev "supported", nbytes);
2864bfbe945Smillert oldusage();
2877baf058cSpvalchev }
2888d1ceb6eSfgsch odadd(fmt[x][y]);
2897baf058cSpvalchev break;
2907baf058cSpvalchev default:
2914bfbe945Smillert oldusage();
2927baf058cSpvalchev }
2937baf058cSpvalchev }
2947baf058cSpvalchev }
2957baf058cSpvalchev
2969844ea72Smmcc static __dead void
oldusage(void)2973921aef3Sderaadt oldusage(void)
2984bfbe945Smillert {
2994bfbe945Smillert extern char *__progname;
3002c7625d7Ssobrado fprintf(stderr, "usage: %s [-aBbcDdeFfHhIiLlOosvXx] [-A base] "
30158d9d1b1Ssobrado "[-j offset] [-N length]\n"
3024ed0fe34Sschwarze "\t[-t type_string] [file ...]\n", __progname);
3034bfbe945Smillert exit(1);
3044bfbe945Smillert }
3054bfbe945Smillert
3067baf058cSpvalchev static void
odoffset(int argc,char *** argvp)3073921aef3Sderaadt odoffset(int argc, char ***argvp)
308df930be7Sderaadt {
309c0932ef1Smpech char *num, *p;
310df930be7Sderaadt int base;
311df930be7Sderaadt char *end;
312df930be7Sderaadt
313df930be7Sderaadt /*
314df930be7Sderaadt * The offset syntax of od(1) was genuinely bizarre. First, if
315df930be7Sderaadt * it started with a plus it had to be an offset. Otherwise, if
316df930be7Sderaadt * there were at least two arguments, a number or lower-case 'x'
317df930be7Sderaadt * followed by a number makes it an offset. By default it was
318df930be7Sderaadt * octal; if it started with 'x' or '0x' it was hex. If it ended
319df930be7Sderaadt * in a '.', it was decimal. If a 'b' or 'B' was appended, it
320df930be7Sderaadt * multiplied the number by 512 or 1024 byte units. There was
321df930be7Sderaadt * no way to assign a block count to a hex offset.
322df930be7Sderaadt *
3237baf058cSpvalchev * We assume it's a file if the offset is bad.
324df930be7Sderaadt */
3257baf058cSpvalchev p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
326df930be7Sderaadt if (!p)
327df930be7Sderaadt return;
3287baf058cSpvalchev
329df930be7Sderaadt if (*p != '+' && (argc < 2 ||
3307baf058cSpvalchev (!isdigit((unsigned char)p[0]) &&
3317baf058cSpvalchev (p[0] != 'x' || !isxdigit((unsigned char)p[1])))))
332df930be7Sderaadt return;
333df930be7Sderaadt
334df930be7Sderaadt base = 0;
335df930be7Sderaadt /*
336df930be7Sderaadt * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
337df930be7Sderaadt * set base.
338df930be7Sderaadt */
339df930be7Sderaadt if (p[0] == '+')
340df930be7Sderaadt ++p;
3417baf058cSpvalchev if (p[0] == 'x' && isxdigit((unsigned char)p[1])) {
342df930be7Sderaadt ++p;
343df930be7Sderaadt base = 16;
344df930be7Sderaadt } else if (p[0] == '0' && p[1] == 'x') {
345df930be7Sderaadt p += 2;
346df930be7Sderaadt base = 16;
347df930be7Sderaadt }
348df930be7Sderaadt
349df930be7Sderaadt /* skip over the number */
350df930be7Sderaadt if (base == 16)
3517baf058cSpvalchev for (num = p; isxdigit((unsigned char)*p); ++p);
352df930be7Sderaadt else
3537baf058cSpvalchev for (num = p; isdigit((unsigned char)*p); ++p);
354df930be7Sderaadt
355df930be7Sderaadt /* check for no number */
356df930be7Sderaadt if (num == p)
357df930be7Sderaadt return;
358df930be7Sderaadt
359df930be7Sderaadt /* if terminates with a '.', base is decimal */
360df930be7Sderaadt if (*p == '.') {
361df930be7Sderaadt if (base)
362df930be7Sderaadt return;
363df930be7Sderaadt base = 10;
364df930be7Sderaadt }
365df930be7Sderaadt
366df930be7Sderaadt skip = strtol(num, &end, base ? base : 8);
367df930be7Sderaadt
368df930be7Sderaadt /* if end isn't the same as p, we got a non-octal digit */
3697baf058cSpvalchev if (end != p) {
370df930be7Sderaadt skip = 0;
3717baf058cSpvalchev return;
3727baf058cSpvalchev }
3737baf058cSpvalchev
3744ed0fe34Sschwarze if (*p == '.')
3754ed0fe34Sschwarze ++p;
376df930be7Sderaadt if (*p) {
3777baf058cSpvalchev if (*p == 'B') {
378df930be7Sderaadt skip *= 1024;
379df930be7Sderaadt ++p;
3807baf058cSpvalchev } else if (*p == 'b') {
3817baf058cSpvalchev skip *= 512;
3827baf058cSpvalchev ++p;
383df930be7Sderaadt }
3847baf058cSpvalchev }
3857baf058cSpvalchev if (*p) {
386df930be7Sderaadt skip = 0;
3877baf058cSpvalchev return;
3887baf058cSpvalchev }
389df930be7Sderaadt /*
3907baf058cSpvalchev * If the offset uses a non-octal base, the base of the offset
3917baf058cSpvalchev * is changed as well. This isn't pretty, but it's easy.
392df930be7Sderaadt */
393df930be7Sderaadt if (base == 16) {
394df930be7Sderaadt fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
395df930be7Sderaadt fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
396df930be7Sderaadt } else if (base == 10) {
397df930be7Sderaadt fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
398df930be7Sderaadt fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
399df930be7Sderaadt }
4007baf058cSpvalchev
4017baf058cSpvalchev /* Terminate file list. */
4024ed0fe34Sschwarze (*argvp)[argc > 1] = NULL;
403df930be7Sderaadt }
404df930be7Sderaadt
405df930be7Sderaadt static void
odadd(const char * format)406*48a8138eStedu odadd(const char *format)
407df930be7Sderaadt {
4088d1ceb6eSfgsch static int needpad;
409df930be7Sderaadt
4108d1ceb6eSfgsch if (needpad)
4118d1ceb6eSfgsch add("\""PADDING"\"");
412*48a8138eStedu add(format);
4138d1ceb6eSfgsch needpad = 1;
414df930be7Sderaadt }
415