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