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