Home | History | Annotate | Line # | Download | only in hexdump
odsyntax.c revision 1.11
      1 /*	$NetBSD: odsyntax.c,v 1.11 2001/02/07 18:32:21 christos 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.11 2001/02/07 18:32:21 christos 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 odprecede __P((void));
     59 
     60 
     61 /*
     62  * formats used for -t
     63  */
     64 static const char *fmt[4][4] = {
     65 	{
     66 		"16/1 \"%3d \" \"\\n\"",
     67 		"8/2  \"  %05d \" \"\\n\"",
     68 		"4/4  \"     %010d \" \"\\n\"",
     69 		"2/8  \" %019d \" \"\\n\""
     70 	}, {
     71 		"16/1 \"%03o \" \"\\n\"",
     72 		"8/2  \" %06o \" \"\\n\"",
     73 		"4/4  \"    %011o\" \"\\n\"",
     74 		"2/8  \" %022o \" \"\\n\""
     75 	}, {
     76 		"16/1 \"%03u \" \"\\n\"",
     77 		"8/2  \"  %05u \" \"\\n\"",
     78 		"4/4  \"     %010u \" \"\\n\"",
     79 		"2/8  \" %020u \" \"\\n\""
     80 	}, {
     81 		"16/1 \" %02x \" \"\\n\"",
     82 		"8/2  \"   %04x \" \"\\n\"",
     83 		"4/4  \"       %08x \" \"\\n\"",
     84 		"2/8  \" %16x \" \"\\n\""
     85 	}
     86 };
     87 
     88 void
     89 oldsyntax(argc, argvp)
     90 	int argc;
     91 	char ***argvp;
     92 {
     93 	int ch;
     94 	char **argv;
     95 	int x, y;
     96 
     97 	deprecated = 1;
     98 	argv = *argvp;
     99 	while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpst:wvXx")) != -1)
    100 		switch (ch) {
    101 		case 'a':
    102 			odprecede();
    103 			add("16/1 \"%3_u \" \"\\n\"");
    104 			break;
    105 		case 'B':
    106 		case 'o':
    107 			odprecede();
    108 			add("8/2 \" %06o \" \"\\n\"");
    109 			break;
    110 		case 'b':
    111 			odprecede();
    112 			add("16/1 \"%03o \" \"\\n\"");
    113 			break;
    114 		case 'c':
    115 			odprecede();
    116 			add("16/1 \"%3_c \" \"\\n\"");
    117 			break;
    118 		case 'd':
    119 			odprecede();
    120 			add("8/2 \"  %05u \" \"\\n\"");
    121 			break;
    122 		case 'D':
    123 			odprecede();
    124 			add("4/4 \"     %010u \" \"\\n\"");
    125 			break;
    126 		case 'e':		/* undocumented in od */
    127 		case 'F':
    128 			odprecede();
    129 			add("2/8 \"          %21.14e \" \"\\n\"");
    130 			break;
    131 
    132 		case 'f':
    133 			odprecede();
    134 			add("4/4 \" %14.7e \" \"\\n\"");
    135 			break;
    136 		case 'H':
    137 		case 'X':
    138 			odprecede();
    139 			add("4/4 \"       %08x \" \"\\n\"");
    140 			break;
    141 		case 'h':
    142 		case 'x':
    143 			odprecede();
    144 			add("8/2 \"   %04x \" \"\\n\"");
    145 			break;
    146 		case 'I':
    147 		case 'L':
    148 		case 'l':
    149 			odprecede();
    150 			add("4/4 \"    %11d \" \"\\n\"");
    151 			break;
    152 		case 'i':
    153 			odprecede();
    154 			add("8/2 \" %6d \" \"\\n\"");
    155 			break;
    156 		case 'O':
    157 			odprecede();
    158 			add("4/4 \"    %011o \" \"\\n\"");
    159 			break;
    160 		case 't':
    161 			for (ch = 0; optarg[ch]; ) {
    162 				odprecede();
    163 				switch (optarg[ch]) {
    164 				case 'a':
    165 					ch++;
    166 					add("16/1 \"%3_u \" \"\\n\"");
    167 					break;
    168 				case 'c':
    169 					ch++;
    170 					add("16/1 \"%3_c \" \"\\n\"");
    171 					break;
    172 				case 'f':
    173 					ch++;
    174 					if      (optarg[ch] == 'F' ||
    175 						 optarg[ch] == '4') {
    176 						ch++;
    177 						add("4/4 \" %14.7e\" \"\\n\"");
    178 					}
    179 					else if (optarg[ch] == 'L' ||
    180 						 optarg[ch] == '8') {
    181 						ch++;
    182 						add("2/8 \" %16.14e\" \"\\n\"");
    183 					}
    184 					else if (optarg[ch] == 'D')
    185 						/* long doubles vary in size */
    186 						usage();
    187 					else
    188 						add("2/8 \" %16.14e\" \"\\n\"");
    189 					break;
    190 				case 'd':
    191 					x = 0;
    192 					goto extensions;
    193 				case 'o':
    194 					x = 1;
    195 					goto extensions;
    196 				case 'u':
    197 					x = 2;
    198 					goto extensions;
    199 				case 'x':
    200 					x = 3;
    201 				extensions:
    202 					ch++;
    203 					y = 2;
    204 					if      (optarg[ch] == 'C' ||
    205 						 optarg[ch] == '1') {
    206 						ch++;
    207 						y = 0;
    208 					}
    209 					else if (optarg[ch] == 'S' ||
    210 						 optarg[ch] == '2') {
    211 						ch++;
    212 						y = 1;
    213 					}
    214 					else if (optarg[ch] == 'I' ||
    215 						 optarg[ch] == '4') {
    216 						ch++;
    217 						y = 2;
    218 					}
    219 					else if (optarg[ch] == 'L' ||
    220 						 optarg[ch] == '8') {
    221 						ch++;
    222 						y = 3;
    223 					}
    224 					add(fmt[x][y]);
    225 					break;
    226 				default:
    227 					usage();
    228 				}
    229 			}
    230 			break;
    231 		case 'v':
    232 			vflag = ALL;
    233 			break;
    234 		case 'P':
    235 		case 'p':
    236 		case 's':
    237 		case 'w':
    238 		case '?':
    239 		default:
    240 			warnx("od(1) has been deprecated for hexdump(1).");
    241 			if (ch != '?')
    242 				warnx(
    243 "hexdump(1) compatibility doesn't support the -%c option%s\n",
    244 				    ch, ch == 's' ? "; see strings(1)." : ".");
    245 			usage();
    246 		}
    247 
    248 	if (!fshead) {
    249 		add("\"%07.7_Ao\n\"");
    250 		add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
    251 	}
    252 
    253 	argc -= optind;
    254 	*argvp += optind;
    255 
    256 	if (argc)
    257 		odoffset(argc, argvp);
    258 }
    259 
    260 static void
    261 odoffset(argc, argvp)
    262 	int argc;
    263 	char ***argvp;
    264 {
    265 	char *num, *p;
    266 	int base;
    267 	char *end;
    268 
    269 	/*
    270 	 * The offset syntax of od(1) was genuinely bizarre.  First, if
    271 	 * it started with a plus it had to be an offset.  Otherwise, if
    272 	 * there were at least two arguments, a number or lower-case 'x'
    273 	 * followed by a number makes it an offset.  By default it was
    274 	 * octal; if it started with 'x' or '0x' it was hex.  If it ended
    275 	 * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
    276 	 * multiplied the number by 512 or 1024 byte units.  There was
    277 	 * no way to assign a block count to a hex offset.
    278 	 *
    279 	 * We assume it's a file if the offset is bad.
    280 	 */
    281 	p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
    282 	if (!p)
    283 		return;
    284 
    285 	if (*p != '+' && (argc < 2 ||
    286 	    (!isdigit((unsigned char)p[0]) &&
    287 	    (p[0] != 'x' || !isxdigit((unsigned char)p[1])))))
    288 		return;
    289 
    290 	base = 0;
    291 	/*
    292 	 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
    293 	 * set base.
    294 	 */
    295 	if (p[0] == '+')
    296 		++p;
    297 	if (p[0] == 'x' && isxdigit((unsigned char)p[1])) {
    298 		++p;
    299 		base = 16;
    300 	} else if (p[0] == '0' && p[1] == 'x') {
    301 		p += 2;
    302 		base = 16;
    303 	}
    304 
    305 	/* skip over the number */
    306 	if (base == 16)
    307 		for (num = p; isxdigit((unsigned char)*p); ++p);
    308 	else
    309 		for (num = p; isdigit((unsigned char)*p); ++p);
    310 
    311 	/* check for no number */
    312 	if (num == p)
    313 		return;
    314 
    315 	/* if terminates with a '.', base is decimal */
    316 	if (*p == '.') {
    317 		if (base)
    318 			return;
    319 		base = 10;
    320 	}
    321 
    322 	skip = strtol(num, &end, base ? base : 8);
    323 
    324 	/* if end isn't the same as p, we got a non-octal digit */
    325 	if (end != p) {
    326 		skip = 0;
    327 		return;
    328 	}
    329 
    330 	if (*p) {
    331 		if (*p == 'B') {
    332 			skip *= 1024;
    333 			++p;
    334 		} else if (*p == 'b') {
    335 			skip *= 512;
    336 			++p;
    337 		}
    338 	}
    339 	if (*p) {
    340 		skip = 0;
    341 		return;
    342 	}
    343 	/*
    344 	 * If the offset uses a non-octal base, the base of the offset
    345 	 * is changed as well.  This isn't pretty, but it's easy.
    346 	 */
    347 #define	TYPE_OFFSET	7
    348 	if (base == 16) {
    349 		fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
    350 		fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
    351 	} else if (base == 10) {
    352 		fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
    353 		fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
    354 	}
    355 
    356 	/* Terminate file list. */
    357 	(*argvp)[1] = NULL;
    358 }
    359 
    360 static void
    361 odprecede()
    362 {
    363 	static int first = 1;
    364 
    365 	if (first) {
    366 		first = 0;
    367 		add("\"%07.7_Ao\n\"");
    368 		add("\"%07.7_ao  \"");
    369 	} else
    370 		add("\"         \"");
    371 }
    372