xref: /original-bsd/usr.bin/hexdump/odsyntax.c (revision 817cfbae)
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.5 (Berkeley) 01/08/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 = **argvp;
146 	if (*p != '+' && (argc < 2 ||
147 	    (!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(p[1])))))
148 		return;
149 
150 	base = 0;
151 	/*
152 	 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
153 	 * set base.
154 	 */
155 	if (p[0] == '+')
156 		++p;
157 	if (p[0] == 'x' && isxdigit(p[1])) {
158 		++p;
159 		base = 16;
160 	} else if (p[0] == '0' && p[1] == 'x') {
161 		p += 2;
162 		base = 16;
163 	}
164 
165 	/* skip over the number */
166 	if (base == 16)
167 		for (num = p; isxdigit(*p); ++p);
168 	else
169 		for (num = p; isdigit(*p); ++p);
170 
171 	/* check for no number */
172 	if (num == p)
173 		return;
174 
175 	/* if terminates with a '.', base is decimal */
176 	if (*p == '.') {
177 		if (base)
178 			return;
179 		base = 10;
180 	}
181 
182 	skip = strtol(num, &end, base ? base : 8);
183 
184 	/* if end isn't the same as p, we got a non-octal digit */
185 	if (end != p)
186 		skip = 0;
187 	else {
188 		if (*p) {
189 			if (*p == 'b')
190 				skip *= 512;
191 			else if (*p == 'B')
192 				skip *= 1024;
193 			++p;
194 		}
195 		if (*p)
196 			skip = 0;
197 		else {
198 			++*argvp;
199 			/*
200 			 * If the offset uses a non-octal base, the base of
201 			 * the offset is changed as well.  This isn't pretty,
202 			 * but it's easy.
203 			 */
204 #define	TYPE_OFFSET	7
205 			if (base == 16) {
206 				fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
207 				fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
208 			} else if (base == 10) {
209 				fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
210 				fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
211 			}
212 		}
213 	}
214 }
215 
216 static void
217 odprecede()
218 {
219 	static int first = 1;
220 
221 	if (first) {
222 		first = 0;
223 		add("\"%07.7_Ao\n\"");
224 		add("\"%07.7_ao  \"");
225 	} else
226 		add("\"         \"");
227 }
228