odsyntax.c revision 92920
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1990, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3527315Scharnier#if 0 3623693Speterstatic char sccsid[] = "@(#)odsyntax.c 8.2 (Berkeley) 5/4/95"; 3727315Scharnier#endif 3827315Scharnierstatic const char rcsid[] = 3950477Speter "$FreeBSD: head/usr.bin/hexdump/odsyntax.c 92920 2002-03-22 01:22:50Z imp $"; 401590Srgrimes#endif /* not lint */ 411590Srgrimes 421590Srgrimes#include <sys/types.h> 431590Srgrimes 4423693Speter#include <ctype.h> 4527315Scharnier#include <err.h> 4623693Speter#include <stdio.h> 471590Srgrimes#include <stdlib.h> 4823693Speter#include <unistd.h> 4923693Speter 501590Srgrimes#include "hexdump.h" 511590Srgrimes 521590Srgrimesint deprecated; 531590Srgrimes 5492920Simpstatic void odoffset(int, char ***); 5592920Simpstatic void odprecede(void); 561590Srgrimes 571590Srgrimesvoid 581590Srgrimesoldsyntax(argc, argvp) 591590Srgrimes int argc; 601590Srgrimes char ***argvp; 611590Srgrimes{ 621590Srgrimes extern enum _vflag vflag; 631590Srgrimes extern FS *fshead; 641590Srgrimes int ch; 651590Srgrimes char **argv; 661590Srgrimes 671590Srgrimes deprecated = 1; 681590Srgrimes argv = *argvp; 6924360Simp while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != -1) 701590Srgrimes switch (ch) { 711590Srgrimes case 'a': 721590Srgrimes odprecede(); 731590Srgrimes add("16/1 \"%3_u \" \"\\n\""); 741590Srgrimes break; 751590Srgrimes case 'B': 761590Srgrimes case 'o': 771590Srgrimes odprecede(); 781590Srgrimes add("8/2 \" %06o \" \"\\n\""); 791590Srgrimes break; 801590Srgrimes case 'b': 811590Srgrimes odprecede(); 821590Srgrimes add("16/1 \"%03o \" \"\\n\""); 831590Srgrimes break; 841590Srgrimes case 'c': 851590Srgrimes odprecede(); 861590Srgrimes add("16/1 \"%3_c \" \"\\n\""); 871590Srgrimes break; 881590Srgrimes case 'd': 891590Srgrimes odprecede(); 901590Srgrimes add("8/2 \" %05u \" \"\\n\""); 911590Srgrimes break; 921590Srgrimes case 'D': 931590Srgrimes odprecede(); 941590Srgrimes add("4/4 \" %010u \" \"\\n\""); 951590Srgrimes break; 961590Srgrimes case 'e': /* undocumented in od */ 971590Srgrimes case 'F': 981590Srgrimes odprecede(); 991590Srgrimes add("2/8 \" %21.14e \" \"\\n\""); 1001590Srgrimes break; 1018874Srgrimes 1021590Srgrimes case 'f': 1031590Srgrimes odprecede(); 1041590Srgrimes add("4/4 \" %14.7e \" \"\\n\""); 1051590Srgrimes break; 1061590Srgrimes case 'H': 1071590Srgrimes case 'X': 1081590Srgrimes odprecede(); 1091590Srgrimes add("4/4 \" %08x \" \"\\n\""); 1101590Srgrimes break; 1111590Srgrimes case 'h': 1121590Srgrimes case 'x': 1131590Srgrimes odprecede(); 1141590Srgrimes add("8/2 \" %04x \" \"\\n\""); 1151590Srgrimes break; 1161590Srgrimes case 'I': 1171590Srgrimes case 'L': 1181590Srgrimes case 'l': 1191590Srgrimes odprecede(); 1201590Srgrimes add("4/4 \" %11d \" \"\\n\""); 1211590Srgrimes break; 1221590Srgrimes case 'i': 1231590Srgrimes odprecede(); 1241590Srgrimes add("8/2 \" %6d \" \"\\n\""); 1251590Srgrimes break; 1261590Srgrimes case 'O': 1271590Srgrimes odprecede(); 1281590Srgrimes add("4/4 \" %011o \" \"\\n\""); 1291590Srgrimes break; 1301590Srgrimes case 'v': 1311590Srgrimes vflag = ALL; 1321590Srgrimes break; 1331590Srgrimes case 'P': 1341590Srgrimes case 'p': 1351590Srgrimes case 's': 1361590Srgrimes case 'w': 1371590Srgrimes case '?': 1381590Srgrimes default: 13927315Scharnier warnx("od(1) has been deprecated for hexdump(1)"); 1401590Srgrimes if (ch != '?') 14127315Scharnier warnx("hexdump(1) compatibility doesn't support the -%c option%s", 14227315Scharnier ch, ch == 's' ? "; see strings(1)" : ""); 1431590Srgrimes usage(); 1441590Srgrimes } 1451590Srgrimes 1461590Srgrimes if (!fshead) { 1471590Srgrimes add("\"%07.7_Ao\n\""); 1481590Srgrimes add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); 1491590Srgrimes } 1501590Srgrimes 1511590Srgrimes argc -= optind; 1521590Srgrimes *argvp += optind; 1531590Srgrimes 1541590Srgrimes if (argc) 1551590Srgrimes odoffset(argc, argvp); 1561590Srgrimes} 1571590Srgrimes 1581590Srgrimesstatic void 1591590Srgrimesodoffset(argc, argvp) 1601590Srgrimes int argc; 1611590Srgrimes char ***argvp; 1621590Srgrimes{ 1631590Srgrimes extern off_t skip; 16430921Sache unsigned char *p, *num, *end; 1651590Srgrimes int base; 1661590Srgrimes 1671590Srgrimes /* 1681590Srgrimes * The offset syntax of od(1) was genuinely bizarre. First, if 1691590Srgrimes * it started with a plus it had to be an offset. Otherwise, if 1701590Srgrimes * there were at least two arguments, a number or lower-case 'x' 1711590Srgrimes * followed by a number makes it an offset. By default it was 1721590Srgrimes * octal; if it started with 'x' or '0x' it was hex. If it ended 1731590Srgrimes * in a '.', it was decimal. If a 'b' or 'B' was appended, it 1741590Srgrimes * multiplied the number by 512 or 1024 byte units. There was 1751590Srgrimes * no way to assign a block count to a hex offset. 1761590Srgrimes * 1771590Srgrimes * We assume it's a file if the offset is bad. 1781590Srgrimes */ 1791590Srgrimes p = argc == 1 ? (*argvp)[0] : (*argvp)[1]; 1801590Srgrimes 1811590Srgrimes if (*p != '+' && (argc < 2 || 1821590Srgrimes (!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(p[1]))))) 1831590Srgrimes return; 1841590Srgrimes 1851590Srgrimes base = 0; 1861590Srgrimes /* 1871590Srgrimes * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and 1881590Srgrimes * set base. 1891590Srgrimes */ 1901590Srgrimes if (p[0] == '+') 1911590Srgrimes ++p; 1921590Srgrimes if (p[0] == 'x' && isxdigit(p[1])) { 1931590Srgrimes ++p; 1941590Srgrimes base = 16; 1951590Srgrimes } else if (p[0] == '0' && p[1] == 'x') { 1961590Srgrimes p += 2; 1971590Srgrimes base = 16; 1981590Srgrimes } 1991590Srgrimes 2001590Srgrimes /* skip over the number */ 2011590Srgrimes if (base == 16) 2021590Srgrimes for (num = p; isxdigit(*p); ++p); 2031590Srgrimes else 2041590Srgrimes for (num = p; isdigit(*p); ++p); 2051590Srgrimes 2061590Srgrimes /* check for no number */ 2071590Srgrimes if (num == p) 2081590Srgrimes return; 2091590Srgrimes 2101590Srgrimes /* if terminates with a '.', base is decimal */ 2111590Srgrimes if (*p == '.') { 2121590Srgrimes if (base) 2131590Srgrimes return; 2141590Srgrimes base = 10; 2151590Srgrimes } 2161590Srgrimes 21782766Sache skip = strtoll(num, (char **)&end, base ? base : 8); 2181590Srgrimes 2191590Srgrimes /* if end isn't the same as p, we got a non-octal digit */ 2201590Srgrimes if (end != p) { 2211590Srgrimes skip = 0; 2221590Srgrimes return; 2231590Srgrimes } 2241590Srgrimes 22548566Sbillf if (*p) { 2261590Srgrimes if (*p == 'B') { 2271590Srgrimes skip *= 1024; 2281590Srgrimes ++p; 2291590Srgrimes } else if (*p == 'b') { 2301590Srgrimes skip *= 512; 2311590Srgrimes ++p; 2321590Srgrimes } 23348566Sbillf } 2341590Srgrimes 2351590Srgrimes if (*p) { 2361590Srgrimes skip = 0; 2371590Srgrimes return; 2381590Srgrimes } 2391590Srgrimes 2401590Srgrimes /* 2411590Srgrimes * If the offset uses a non-octal base, the base of the offset 2421590Srgrimes * is changed as well. This isn't pretty, but it's easy. 2431590Srgrimes */ 2441590Srgrimes#define TYPE_OFFSET 7 2451590Srgrimes if (base == 16) { 2461590Srgrimes fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; 2471590Srgrimes fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; 2481590Srgrimes } else if (base == 10) { 2491590Srgrimes fshead->nextfu->fmt[TYPE_OFFSET] = 'd'; 2501590Srgrimes fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd'; 2511590Srgrimes } 2521590Srgrimes 2531590Srgrimes /* Terminate file list. */ 2541590Srgrimes (*argvp)[1] = NULL; 2551590Srgrimes} 2561590Srgrimes 2571590Srgrimesstatic void 2581590Srgrimesodprecede() 2591590Srgrimes{ 2601590Srgrimes static int first = 1; 2611590Srgrimes 2621590Srgrimes if (first) { 2631590Srgrimes first = 0; 2641590Srgrimes add("\"%07.7_Ao\n\""); 2651590Srgrimes add("\"%07.7_ao \""); 2661590Srgrimes } else 2671590Srgrimes add("\" \""); 2681590Srgrimes} 269