odsyntax.c revision 1.14 1 /* $NetBSD: odsyntax.c,v 1.14 2001/12/07 01:23:42 bjh21 Exp $ */
2
3 /*-
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)odsyntax.c 8.2 (Berkeley) 5/4/95";
40 #else
41 __RCSID("$NetBSD: odsyntax.c,v 1.14 2001/12/07 01:23:42 bjh21 Exp $");
42 #endif
43 #endif /* not lint */
44
45 #include <sys/types.h>
46
47 #include <ctype.h>
48 #include <err.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52
53 #include "hexdump.h"
54
55 int deprecated;
56
57 static void odoffset __P((int, char ***));
58 static void posixtypes __P((char *));
59 static void odprecede __P((void));
60
61
62 /*
63 * formats used for -t
64 */
65 static const char *fmt[4][4] = {
66 {
67 "16/1 \"%3d \" \"\\n\"",
68 "8/2 \" %05d \" \"\\n\"",
69 "4/4 \" %010d \" \"\\n\"",
70 "2/8 \" %019d \" \"\\n\""
71 }, {
72 "16/1 \"%03o \" \"\\n\"",
73 "8/2 \" %06o \" \"\\n\"",
74 "4/4 \" %011o\" \"\\n\"",
75 "2/8 \" %022o \" \"\\n\""
76 }, {
77 "16/1 \"%03u \" \"\\n\"",
78 "8/2 \" %05u \" \"\\n\"",
79 "4/4 \" %010u \" \"\\n\"",
80 "2/8 \" %020u \" \"\\n\""
81 }, {
82 "16/1 \" %02x \" \"\\n\"",
83 "8/2 \" %04x \" \"\\n\"",
84 "4/4 \" %08x \" \"\\n\"",
85 "2/8 \" %16x \" \"\\n\""
86 }
87 };
88
89 void
90 oldsyntax(argc, argvp)
91 int argc;
92 char ***argvp;
93 {
94 int ch;
95 char *p, **argv;
96
97 deprecated = 1;
98 argv = *argvp;
99 while ((ch = getopt(argc, argv,
100 "aBbcDdeFfHhIij:LlN:OoPpst:wvXx")) != -1)
101 switch (ch) {
102 case 'a':
103 odprecede();
104 add("16/1 \"%3_u \" \"\\n\"");
105 break;
106 case 'B':
107 case 'o':
108 odprecede();
109 add("8/2 \" %06o \" \"\\n\"");
110 break;
111 case 'b':
112 odprecede();
113 add("16/1 \"%03o \" \"\\n\"");
114 break;
115 case 'c':
116 odprecede();
117 add("16/1 \"%3_c \" \"\\n\"");
118 break;
119 case 'd':
120 odprecede();
121 add("8/2 \" %05u \" \"\\n\"");
122 break;
123 case 'D':
124 odprecede();
125 add("4/4 \" %010u \" \"\\n\"");
126 break;
127 case 'e': /* undocumented in od */
128 case 'F':
129 odprecede();
130 add("2/8 \" %21.14e \" \"\\n\"");
131 break;
132
133 case 'f':
134 odprecede();
135 add("4/4 \" %14.7e \" \"\\n\"");
136 break;
137 case 'H':
138 case 'X':
139 odprecede();
140 add("4/4 \" %08x \" \"\\n\"");
141 break;
142 case 'h':
143 case 'x':
144 odprecede();
145 add("8/2 \" %04x \" \"\\n\"");
146 break;
147 case 'I':
148 case 'L':
149 case 'l':
150 odprecede();
151 add("4/4 \" %11d \" \"\\n\"");
152 break;
153 case 'i':
154 odprecede();
155 add("8/2 \" %6d \" \"\\n\"");
156 break;
157 case 'j':
158 if ((skip = strtol(optarg, &p, 0)) < 0)
159 errx(1, "%s: bad skip value", optarg);
160 switch(*p) {
161 case 'b':
162 skip *= 512;
163 break;
164 case 'k':
165 skip *= 1024;
166 break;
167 case 'm':
168 skip *= 1048576;
169 break;
170 }
171 break;
172 case 'N':
173 if ((length = atoi(optarg)) < 0)
174 errx(1, "%s: bad length value", optarg);
175 break;
176 case 'O':
177 odprecede();
178 add("4/4 \" %011o \" \"\\n\"");
179 break;
180 case 't':
181 posixtypes(optarg);
182 break;
183 case 'v':
184 vflag = ALL;
185 break;
186 case 'P':
187 case 'p':
188 case 's':
189 case 'w':
190 case '?':
191 default:
192 warnx("od(1) has been deprecated for hexdump(1).");
193 if (ch != '?')
194 warnx(
195 "hexdump(1) compatibility doesn't support the -%c option%s\n",
196 ch, ch == 's' ? "; see strings(1)." : ".");
197 usage();
198 }
199
200 if (!fshead) {
201 add("\"%07.7_Ao\n\"");
202 add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\"");
203 }
204
205 argc -= optind;
206 *argvp += optind;
207
208 if (argc)
209 odoffset(argc, argvp);
210 }
211
212 /*
213 * Interpret a POSIX-style -t argument.
214 */
215 static void
216 posixtypes(type_string)
217 char *type_string;
218 {
219 int x, y, size;
220
221 while (*type_string) {
222 odprecede();
223 switch (*type_string) {
224 case 'a':
225 type_string++;
226 add("16/1 \"%3_u \" \"\\n\"");
227 break;
228 case 'c':
229 type_string++;
230 add("16/1 \"%3_c \" \"\\n\"");
231 break;
232 case 'f':
233 type_string++;
234 if (*type_string == 'F' ||
235 *type_string == '4') {
236 type_string++;
237 add("4/4 \" %14.7e\" \"\\n\"");
238 } else if (*type_string == 'L' ||
239 *type_string == '8') {
240 type_string++;
241 add("2/8 \" %16.14e\" \"\\n\"");
242 } else if (*type_string == 'D')
243 /* long doubles vary in size */
244 usage();
245 else
246 add("2/8 \" %16.14e\" \"\\n\"");
247 break;
248 case 'd':
249 x = 0;
250 goto extensions;
251 case 'o':
252 x = 1;
253 goto extensions;
254 case 'u':
255 x = 2;
256 goto extensions;
257 case 'x':
258 x = 3;
259 extensions:
260 type_string++;
261 y = 2;
262 if (isupper(*type_string)) {
263 switch(*type_string) {
264 case 'C':
265 size = sizeof(char);
266 break;
267 case 'S':
268 size = sizeof(short);
269 break;
270 case 'I':
271 size = sizeof(int);
272 break;
273 case 'L':
274 size = sizeof(long);
275 break;
276 default:
277 warnx("Bad type-size qualifier '%c'",
278 *type_string);
279 usage();
280 }
281 type_string++;
282 } else if (isdigit(*type_string))
283 size = strtol(type_string, &type_string, 10);
284
285 switch (size) {
286 case 1:
287 y = 0;
288 break;
289 case 2:
290 y = 1;
291 break;
292 case 4:
293 y = 2;
294 break;
295 case 8:
296 y = 3;
297 break;
298 default:
299 warnx("%d-byte integer formats are not "
300 "supported", size);
301 usage();
302 }
303 add(fmt[x][y]);
304 break;
305 default:
306 usage();
307 }
308 }
309 }
310
311 static void
312 odoffset(argc, argvp)
313 int argc;
314 char ***argvp;
315 {
316 char *num, *p;
317 int base;
318 char *end;
319
320 /*
321 * The offset syntax of od(1) was genuinely bizarre. First, if
322 * it started with a plus it had to be an offset. Otherwise, if
323 * there were at least two arguments, a number or lower-case 'x'
324 * followed by a number makes it an offset. By default it was
325 * octal; if it started with 'x' or '0x' it was hex. If it ended
326 * in a '.', it was decimal. If a 'b' or 'B' was appended, it
327 * multiplied the number by 512 or 1024 byte units. There was
328 * no way to assign a block count to a hex offset.
329 *
330 * We assume it's a file if the offset is bad.
331 */
332 p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
333 if (!p)
334 return;
335
336 if (*p != '+' && (argc < 2 ||
337 (!isdigit((unsigned char)p[0]) &&
338 (p[0] != 'x' || !isxdigit((unsigned char)p[1])))))
339 return;
340
341 base = 0;
342 /*
343 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
344 * set base.
345 */
346 if (p[0] == '+')
347 ++p;
348 if (p[0] == 'x' && isxdigit((unsigned char)p[1])) {
349 ++p;
350 base = 16;
351 } else if (p[0] == '0' && p[1] == 'x') {
352 p += 2;
353 base = 16;
354 }
355
356 /* skip over the number */
357 if (base == 16)
358 for (num = p; isxdigit((unsigned char)*p); ++p);
359 else
360 for (num = p; isdigit((unsigned char)*p); ++p);
361
362 /* check for no number */
363 if (num == p)
364 return;
365
366 /* if terminates with a '.', base is decimal */
367 if (*p == '.') {
368 if (base)
369 return;
370 base = 10;
371 }
372
373 skip = strtol(num, &end, base ? base : 8);
374
375 /* if end isn't the same as p, we got a non-octal digit */
376 if (end != p) {
377 skip = 0;
378 return;
379 }
380
381 if (*p) {
382 if (*p == 'B') {
383 skip *= 1024;
384 ++p;
385 } else if (*p == 'b') {
386 skip *= 512;
387 ++p;
388 }
389 }
390 if (*p) {
391 skip = 0;
392 return;
393 }
394 /*
395 * If the offset uses a non-octal base, the base of the offset
396 * is changed as well. This isn't pretty, but it's easy.
397 */
398 #define TYPE_OFFSET 7
399 if (base == 16) {
400 fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
401 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
402 } else if (base == 10) {
403 fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
404 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
405 }
406
407 /* Terminate file list. */
408 (*argvp)[1] = NULL;
409 }
410
411 static void
412 odprecede()
413 {
414 static int first = 1;
415
416 if (first) {
417 first = 0;
418 add("\"%07.7_Ao\n\"");
419 add("\"%07.7_ao \"");
420 } else
421 add("\" \"");
422 }
423