1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)odsyntax.c 8.1 (Berkeley) 06/06/93"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 14 #include <stdlib.h> 15 #include <stdio.h> 16 #include <ctype.h> 17 #include "hexdump.h" 18 19 int deprecated; 20 21 static void odoffset __P((int, char ***)); 22 static void odprecede __P((void)); 23 24 void 25 oldsyntax(argc, argvp) 26 int argc; 27 char ***argvp; 28 { 29 extern enum _vflag vflag; 30 extern FS *fshead; 31 int ch; 32 char **argv; 33 34 deprecated = 1; 35 argv = *argvp; 36 while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF) 37 switch (ch) { 38 case 'a': 39 odprecede(); 40 add("16/1 \"%3_u \" \"\\n\""); 41 break; 42 case 'B': 43 case 'o': 44 odprecede(); 45 add("8/2 \" %06o \" \"\\n\""); 46 break; 47 case 'b': 48 odprecede(); 49 add("16/1 \"%03o \" \"\\n\""); 50 break; 51 case 'c': 52 odprecede(); 53 add("16/1 \"%3_c \" \"\\n\""); 54 break; 55 case 'd': 56 odprecede(); 57 add("8/2 \" %05u \" \"\\n\""); 58 break; 59 case 'D': 60 odprecede(); 61 add("4/4 \" %010u \" \"\\n\""); 62 break; 63 case 'e': /* undocumented in od */ 64 case 'F': 65 odprecede(); 66 add("2/8 \" %21.14e \" \"\\n\""); 67 break; 68 69 case 'f': 70 odprecede(); 71 add("4/4 \" %14.7e \" \"\\n\""); 72 break; 73 case 'H': 74 case 'X': 75 odprecede(); 76 add("4/4 \" %08x \" \"\\n\""); 77 break; 78 case 'h': 79 case 'x': 80 odprecede(); 81 add("8/2 \" %04x \" \"\\n\""); 82 break; 83 case 'I': 84 case 'L': 85 case 'l': 86 odprecede(); 87 add("4/4 \" %11d \" \"\\n\""); 88 break; 89 case 'i': 90 odprecede(); 91 add("8/2 \" %6d \" \"\\n\""); 92 break; 93 case 'O': 94 odprecede(); 95 add("4/4 \" %011o \" \"\\n\""); 96 break; 97 case 'v': 98 vflag = ALL; 99 break; 100 case 'P': 101 case 'p': 102 case 's': 103 case 'w': 104 case '?': 105 default: 106 (void)fprintf(stderr, 107 "od: od(1) has been deprecated for hexdump(1).\n"); 108 if (ch != '?') 109 (void)fprintf(stderr, 110 "od: hexdump(1) compatibility doesn't support the -%c option%s\n", 111 ch, ch == 's' ? "; see strings(1)." : "."); 112 usage(); 113 } 114 115 if (!fshead) { 116 add("\"%07.7_Ao\n\""); 117 add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); 118 } 119 120 argc -= optind; 121 *argvp += optind; 122 123 if (argc) 124 odoffset(argc, argvp); 125 } 126 127 static void 128 odoffset(argc, argvp) 129 int argc; 130 char ***argvp; 131 { 132 extern off_t skip; 133 register char *num, *p; 134 int base; 135 char *end; 136 137 /* 138 * The offset syntax of od(1) was genuinely bizarre. First, if 139 * it started with a plus it had to be an offset. Otherwise, if 140 * there were at least two arguments, a number or lower-case 'x' 141 * followed by a number makes it an offset. By default it was 142 * octal; if it started with 'x' or '0x' it was hex. If it ended 143 * in a '.', it was decimal. If a 'b' or 'B' was appended, it 144 * multiplied the number by 512 or 1024 byte units. There was 145 * no way to assign a block count to a hex offset. 146 * 147 * We assume it's a file if the offset is bad. 148 */ 149 p = argc == 1 ? (*argvp)[0] : (*argvp)[1]; 150 151 if (*p != '+' && (argc < 2 || 152 (!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(p[1]))))) 153 return; 154 155 base = 0; 156 /* 157 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and 158 * set base. 159 */ 160 if (p[0] == '+') 161 ++p; 162 if (p[0] == 'x' && isxdigit(p[1])) { 163 ++p; 164 base = 16; 165 } else if (p[0] == '0' && p[1] == 'x') { 166 p += 2; 167 base = 16; 168 } 169 170 /* skip over the number */ 171 if (base == 16) 172 for (num = p; isxdigit(*p); ++p); 173 else 174 for (num = p; isdigit(*p); ++p); 175 176 /* check for no number */ 177 if (num == p) 178 return; 179 180 /* if terminates with a '.', base is decimal */ 181 if (*p == '.') { 182 if (base) 183 return; 184 base = 10; 185 } 186 187 skip = strtol(num, &end, base ? base : 8); 188 189 /* if end isn't the same as p, we got a non-octal digit */ 190 if (end != p) { 191 skip = 0; 192 return; 193 } 194 195 if (*p) 196 if (*p == 'B') { 197 skip *= 1024; 198 ++p; 199 } else if (*p == 'b') { 200 skip *= 512; 201 ++p; 202 } 203 204 if (*p) { 205 skip = 0; 206 return; 207 } 208 209 /* 210 * If the offset uses a non-octal base, the base of the offset 211 * is changed as well. This isn't pretty, but it's easy. 212 */ 213 #define TYPE_OFFSET 7 214 if (base == 16) { 215 fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; 216 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; 217 } else if (base == 10) { 218 fshead->nextfu->fmt[TYPE_OFFSET] = 'd'; 219 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd'; 220 } 221 222 /* Terminate file list. */ 223 (*argvp)[1] = NULL; 224 } 225 226 static void 227 odprecede() 228 { 229 static int first = 1; 230 231 if (first) { 232 first = 0; 233 add("\"%07.7_Ao\n\""); 234 add("\"%07.7_ao \""); 235 } else 236 add("\" \""); 237 } 238