xref: /original-bsd/usr.bin/hexdump/odsyntax.c (revision 56c13d2e)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)odsyntax.c	5.4 (Berkeley) 03/08/91";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include "hexdump.h"
16 
17 int deprecated;
18 
19 oldsyntax(argc, argvp)
20 	int argc;
21 	char ***argvp;
22 {
23 	extern enum _vflag vflag;
24 	extern FS *fshead;
25 	extern char *optarg;
26 	extern int length, optind;
27 	int ch;
28 	char **argv;
29 	static void odprecede();
30 
31 	deprecated = 1;
32 	argv = *argvp;
33 	while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF)
34 		switch (ch) {
35 		case 'a':
36 			odprecede();
37 			add("16/1 \"%3_u \" \"\\n\"");
38 			break;
39 		case 'B':
40 		case 'o':
41 			odprecede();
42 			add("8/2 \" %06o \" \"\\n\"");
43 			break;
44 		case 'b':
45 			odprecede();
46 			add("16/1 \"%03o \" \"\\n\"");
47 			break;
48 		case 'c':
49 			odprecede();
50 			add("16/1 \"%3_c \" \"\\n\"");
51 			break;
52 		case 'd':
53 			odprecede();
54 			add("8/2 \"  %05u \" \"\\n\"");
55 			break;
56 		case 'D':
57 			odprecede();
58 			add("4/4 \"     %010u \" \"\\n\"");
59 			break;
60 		case 'e':		/* undocumented in od */
61 		case 'F':
62 			odprecede();
63 			add("2/8 \"          %21.14e \" \"\\n\"");
64 			break;
65 
66 		case 'f':
67 			odprecede();
68 			add("4/4 \" %14.7e \" \"\\n\"");
69 			break;
70 		case 'H':
71 		case 'X':
72 			odprecede();
73 			add("4/4 \"       %08x \" \"\\n\"");
74 			break;
75 		case 'h':
76 		case 'x':
77 			odprecede();
78 			add("8/2 \"   %04x \" \"\\n\"");
79 			break;
80 		case 'I':
81 		case 'L':
82 		case 'l':
83 			odprecede();
84 			add("4/4 \"    %11d \" \"\\n\"");
85 			break;
86 		case 'i':
87 			odprecede();
88 			add("8/2 \" %6d \" \"\\n\"");
89 			break;
90 		case 'O':
91 			odprecede();
92 			add("4/4 \"    %011o \" \"\\n\"");
93 			break;
94 		case 'v':
95 			vflag = ALL;
96 			break;
97 		case 'P':
98 		case 'p':
99 		case 's':
100 		case 'w':
101 		case '?':
102 		default:
103 			(void)fprintf(stderr,
104 			    "od: od(1) has been deprecated for hexdump(1).\n");
105 			if (ch != '?')
106 				(void)fprintf(stderr,
107 "od: hexdump(1) compatibility doesn't support the -%c option%s\n",
108 				    ch, ch == 's' ? "; see strings(1)." : ".");
109 			usage();
110 		}
111 
112 	if (!fshead) {
113 		add("\"%07.7_Ao\n\"");
114 		add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
115 	}
116 
117 	argc -= optind;
118 	*argvp += optind;
119 
120 	odoffset(argc, argvp);
121 }
122 
123 #define	ishexdigit(c) \
124 	(c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F')
125 
126 odoffset(argc, argvp)
127 	int argc;
128 	char ***argvp;
129 {
130 	extern off_t skip;
131 	register char *num, *p;
132 	int base;
133 	char *end;
134 
135 	/*
136 	 * The offset syntax of od(1) was genuinely bizarre.  First, if
137 	 * it started with a plus it had to be an offset.  Otherwise, if
138 	 * there were at least two arguments, a number or lower-case 'x'
139 	 * followed by a number makes it an offset.  By default it was
140 	 * octal; if it started with 'x' or '0x' it was hex.  If it ended
141 	 * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
142 	 * multiplied the number by 512 or 1024 byte units.  There was
143 	 * no way to assign a block count to a hex offset.
144 	 *
145 	 * We assumes it's a file if the offset is bad.
146 	 */
147 	p = **argvp;
148 	if (*p != '+' && (argc < 2 ||
149 	    (!isdigit(p[0]) && (p[0] != 'x' || !ishexdigit(p[1])))))
150 		return;
151 
152 	base = 0;
153 	/*
154 	 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
155 	 * set base.
156 	 */
157 	if (p[0] == '+')
158 		++p;
159 	if (p[0] == 'x' && ishexdigit(p[1])) {
160 		++p;
161 		base = 16;
162 	} else if (p[0] == '0' && p[1] == 'x') {
163 		p += 2;
164 		base = 16;
165 	}
166 
167 	/* skip over the number */
168 	if (base == 16)
169 		for (num = p; ishexdigit(*p); ++p);
170 	else
171 		for (num = p; isdigit(*p); ++p);
172 
173 	/* check for no number */
174 	if (num == p)
175 		return;
176 
177 	/* if terminates with a '.', base is decimal */
178 	if (*p == '.') {
179 		if (base)
180 			return;
181 		base = 10;
182 	}
183 
184 	skip = strtol(num, &end, base ? base : 8);
185 
186 	/* if end isn't the same as p, we got a non-octal digit */
187 	if (end != p)
188 		skip = 0;
189 	else {
190 		if (*p) {
191 			if (*p == 'b')
192 				skip *= 512;
193 			else if (*p == 'B')
194 				skip *= 1024;
195 			++p;
196 		}
197 		if (*p)
198 			skip = 0;
199 		else {
200 			++*argvp;
201 			/*
202 			 * If the offset uses a non-octal base, the base of
203 			 * the offset is changed as well.  This isn't pretty,
204 			 * but it's easy.
205 			 */
206 #define	TYPE_OFFSET	7
207 			if (base == 16) {
208 				fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
209 				fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
210 			} else if (base == 10) {
211 				fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
212 				fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
213 			}
214 		}
215 	}
216 }
217 
218 static void
219 odprecede()
220 {
221 	static int first = 1;
222 
223 	if (first) {
224 		first = 0;
225 		add("\"%07.7_Ao\n\"");
226 		add("\"%07.7_ao  \"");
227 	} else
228 		add("\"         \"");
229 }
230