xref: /freebsd/usr.bin/hexdump/odsyntax.c (revision b7a1a0a5ff8895e6a5c9404d02357ac9e2eb8091)
1 /*-
2  * Copyright (c) 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 static char sccsid[] = "@(#)odsyntax.c	8.1 (Berkeley) 6/6/93";
36 #endif /* not lint */
37 
38 #include <sys/types.h>
39 
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <ctype.h>
43 #include "hexdump.h"
44 
45 int deprecated;
46 
47 static void odoffset __P((int, char ***));
48 static void odprecede __P((void));
49 
50 void
51 oldsyntax(argc, argvp)
52 	int argc;
53 	char ***argvp;
54 {
55 	extern enum _vflag vflag;
56 	extern FS *fshead;
57 	int ch;
58 	char **argv;
59 
60 	deprecated = 1;
61 	argv = *argvp;
62 	while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF)
63 		switch (ch) {
64 		case 'a':
65 			odprecede();
66 			add("16/1 \"%3_u \" \"\\n\"");
67 			break;
68 		case 'B':
69 		case 'o':
70 			odprecede();
71 			add("8/2 \" %06o \" \"\\n\"");
72 			break;
73 		case 'b':
74 			odprecede();
75 			add("16/1 \"%03o \" \"\\n\"");
76 			break;
77 		case 'c':
78 			odprecede();
79 			add("16/1 \"%3_c \" \"\\n\"");
80 			break;
81 		case 'd':
82 			odprecede();
83 			add("8/2 \"  %05u \" \"\\n\"");
84 			break;
85 		case 'D':
86 			odprecede();
87 			add("4/4 \"     %010u \" \"\\n\"");
88 			break;
89 		case 'e':		/* undocumented in od */
90 		case 'F':
91 			odprecede();
92 			add("2/8 \"          %21.14e \" \"\\n\"");
93 			break;
94 
95 		case 'f':
96 			odprecede();
97 			add("4/4 \" %14.7e \" \"\\n\"");
98 			break;
99 		case 'H':
100 		case 'X':
101 			odprecede();
102 			add("4/4 \"       %08x \" \"\\n\"");
103 			break;
104 		case 'h':
105 		case 'x':
106 			odprecede();
107 			add("8/2 \"   %04x \" \"\\n\"");
108 			break;
109 		case 'I':
110 		case 'L':
111 		case 'l':
112 			odprecede();
113 			add("4/4 \"    %11d \" \"\\n\"");
114 			break;
115 		case 'i':
116 			odprecede();
117 			add("8/2 \" %6d \" \"\\n\"");
118 			break;
119 		case 'O':
120 			odprecede();
121 			add("4/4 \"    %011o \" \"\\n\"");
122 			break;
123 		case 'v':
124 			vflag = ALL;
125 			break;
126 		case 'P':
127 		case 'p':
128 		case 's':
129 		case 'w':
130 		case '?':
131 		default:
132 			(void)fprintf(stderr,
133 			    "od: od(1) has been deprecated for hexdump(1).\n");
134 			if (ch != '?')
135 				(void)fprintf(stderr,
136 "od: hexdump(1) compatibility doesn't support the -%c option%s\n",
137 				    ch, ch == 's' ? "; see strings(1)." : ".");
138 			usage();
139 		}
140 
141 	if (!fshead) {
142 		add("\"%07.7_Ao\n\"");
143 		add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
144 	}
145 
146 	argc -= optind;
147 	*argvp += optind;
148 
149 	if (argc)
150 		odoffset(argc, argvp);
151 }
152 
153 static void
154 odoffset(argc, argvp)
155 	int argc;
156 	char ***argvp;
157 {
158 	extern off_t skip;
159 	register char *num, *p;
160 	int base;
161 	char *end;
162 
163 	/*
164 	 * The offset syntax of od(1) was genuinely bizarre.  First, if
165 	 * it started with a plus it had to be an offset.  Otherwise, if
166 	 * there were at least two arguments, a number or lower-case 'x'
167 	 * followed by a number makes it an offset.  By default it was
168 	 * octal; if it started with 'x' or '0x' it was hex.  If it ended
169 	 * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
170 	 * multiplied the number by 512 or 1024 byte units.  There was
171 	 * no way to assign a block count to a hex offset.
172 	 *
173 	 * We assume it's a file if the offset is bad.
174 	 */
175 	p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
176 
177 	if (*p != '+' && (argc < 2 ||
178 	    (!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(p[1])))))
179 		return;
180 
181 	base = 0;
182 	/*
183 	 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
184 	 * set base.
185 	 */
186 	if (p[0] == '+')
187 		++p;
188 	if (p[0] == 'x' && isxdigit(p[1])) {
189 		++p;
190 		base = 16;
191 	} else if (p[0] == '0' && p[1] == 'x') {
192 		p += 2;
193 		base = 16;
194 	}
195 
196 	/* skip over the number */
197 	if (base == 16)
198 		for (num = p; isxdigit(*p); ++p);
199 	else
200 		for (num = p; isdigit(*p); ++p);
201 
202 	/* check for no number */
203 	if (num == p)
204 		return;
205 
206 	/* if terminates with a '.', base is decimal */
207 	if (*p == '.') {
208 		if (base)
209 			return;
210 		base = 10;
211 	}
212 
213 	skip = strtol(num, &end, base ? base : 8);
214 
215 	/* if end isn't the same as p, we got a non-octal digit */
216 	if (end != p) {
217 		skip = 0;
218 		return;
219 	}
220 
221 	if (*p)
222 		if (*p == 'B') {
223 			skip *= 1024;
224 			++p;
225 		} else if (*p == 'b') {
226 			skip *= 512;
227 			++p;
228 		}
229 
230 	if (*p) {
231 		skip = 0;
232 		return;
233 	}
234 
235 	/*
236 	 * If the offset uses a non-octal base, the base of the offset
237 	 * is changed as well.  This isn't pretty, but it's easy.
238 	 */
239 #define	TYPE_OFFSET	7
240 	if (base == 16) {
241 		fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
242 		fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
243 	} else if (base == 10) {
244 		fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
245 		fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
246 	}
247 
248 	/* Terminate file list. */
249 	(*argvp)[1] = NULL;
250 }
251 
252 static void
253 odprecede()
254 {
255 	static int first = 1;
256 
257 	if (first) {
258 		first = 0;
259 		add("\"%07.7_Ao\n\"");
260 		add("\"%07.7_ao  \"");
261 	} else
262 		add("\"         \"");
263 }
264