1 /* $NetBSD: odsyntax.c,v 1.15 2001/12/07 15:14:29 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.15 2001/12/07 15:14:29 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, nbytes; 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 nbytes = sizeof(char); 266 break; 267 case 'S': 268 nbytes = sizeof(short); 269 break; 270 case 'I': 271 nbytes = sizeof(int); 272 break; 273 case 'L': 274 nbytes = 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 nbytes = strtol(type_string, &type_string, 10); 284 285 switch (nbytes) { 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", nbytes); 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