xref: /original-bsd/usr.bin/hexdump/odsyntax.c (revision 753853ba)
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.6 (Berkeley) 03/02/92";
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 	if (argc)
121 		odoffset(argc, argvp);
122 }
123 
124 odoffset(argc, argvp)
125 	int argc;
126 	char ***argvp;
127 {
128 	extern off_t skip;
129 	register char *num, *p;
130 	int base;
131 	char *end;
132 
133 	/*
134 	 * The offset syntax of od(1) was genuinely bizarre.  First, if
135 	 * it started with a plus it had to be an offset.  Otherwise, if
136 	 * there were at least two arguments, a number or lower-case 'x'
137 	 * followed by a number makes it an offset.  By default it was
138 	 * octal; if it started with 'x' or '0x' it was hex.  If it ended
139 	 * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
140 	 * multiplied the number by 512 or 1024 byte units.  There was
141 	 * no way to assign a block count to a hex offset.
142 	 *
143 	 * We assume it's a file if the offset is bad.
144 	 */
145 	p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
146 
147 	if (*p != '+' && (argc < 2 ||
148 	    (!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(p[1])))))
149 		return;
150 
151 	base = 0;
152 	/*
153 	 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
154 	 * set base.
155 	 */
156 	if (p[0] == '+')
157 		++p;
158 	if (p[0] == 'x' && isxdigit(p[1])) {
159 		++p;
160 		base = 16;
161 	} else if (p[0] == '0' && p[1] == 'x') {
162 		p += 2;
163 		base = 16;
164 	}
165 
166 	/* skip over the number */
167 	if (base == 16)
168 		for (num = p; isxdigit(*p); ++p);
169 	else
170 		for (num = p; isdigit(*p); ++p);
171 
172 	/* check for no number */
173 	if (num == p)
174 		return;
175 
176 	/* if terminates with a '.', base is decimal */
177 	if (*p == '.') {
178 		if (base)
179 			return;
180 		base = 10;
181 	}
182 
183 	skip = strtol(num, &end, base ? base : 8);
184 
185 	/* if end isn't the same as p, we got a non-octal digit */
186 	if (end != p) {
187 		skip = 0;
188 		return;
189 	}
190 
191 	if (*p)
192 		if (*p == 'B') {
193 			skip *= 1024;
194 			++p;
195 		} else if (*p == 'b') {
196 			skip *= 512;
197 			++p;
198 		}
199 
200 	if (*p) {
201 		skip = 0;
202 		return;
203 	}
204 
205 	/*
206 	 * If the offset uses a non-octal base, the base of the offset
207 	 * is changed as well.  This isn't pretty, but it's easy.
208 	 */
209 #define	TYPE_OFFSET	7
210 	if (base == 16) {
211 		fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
212 		fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
213 	} else if (base == 10) {
214 		fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
215 		fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
216 	}
217 
218 	/* Terminate file list. */
219 	(*argvp)[1] = NULL;
220 }
221 
222 static void
223 odprecede()
224 {
225 	static int first = 1;
226 
227 	if (first) {
228 		first = 0;
229 		add("\"%07.7_Ao\n\"");
230 		add("\"%07.7_ao  \"");
231 	} else
232 		add("\"         \"");
233 }
234