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