GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/hexdump/odsyntax.c Lines: 0 172 0.0 %
Date: 2016-12-06 Branches: 0 125 0.0 %

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