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