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