1 /* $NetBSD: odsyntax.c,v 1.11 2001/02/07 18:32:21 christos 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.11 2001/02/07 18:32:21 christos 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 odprecede __P((void)); 59 60 61 /* 62 * formats used for -t 63 */ 64 static const char *fmt[4][4] = { 65 { 66 "16/1 \"%3d \" \"\\n\"", 67 "8/2 \" %05d \" \"\\n\"", 68 "4/4 \" %010d \" \"\\n\"", 69 "2/8 \" %019d \" \"\\n\"" 70 }, { 71 "16/1 \"%03o \" \"\\n\"", 72 "8/2 \" %06o \" \"\\n\"", 73 "4/4 \" %011o\" \"\\n\"", 74 "2/8 \" %022o \" \"\\n\"" 75 }, { 76 "16/1 \"%03u \" \"\\n\"", 77 "8/2 \" %05u \" \"\\n\"", 78 "4/4 \" %010u \" \"\\n\"", 79 "2/8 \" %020u \" \"\\n\"" 80 }, { 81 "16/1 \" %02x \" \"\\n\"", 82 "8/2 \" %04x \" \"\\n\"", 83 "4/4 \" %08x \" \"\\n\"", 84 "2/8 \" %16x \" \"\\n\"" 85 } 86 }; 87 88 void 89 oldsyntax(argc, argvp) 90 int argc; 91 char ***argvp; 92 { 93 int ch; 94 char **argv; 95 int x, y; 96 97 deprecated = 1; 98 argv = *argvp; 99 while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpst:wvXx")) != -1) 100 switch (ch) { 101 case 'a': 102 odprecede(); 103 add("16/1 \"%3_u \" \"\\n\""); 104 break; 105 case 'B': 106 case 'o': 107 odprecede(); 108 add("8/2 \" %06o \" \"\\n\""); 109 break; 110 case 'b': 111 odprecede(); 112 add("16/1 \"%03o \" \"\\n\""); 113 break; 114 case 'c': 115 odprecede(); 116 add("16/1 \"%3_c \" \"\\n\""); 117 break; 118 case 'd': 119 odprecede(); 120 add("8/2 \" %05u \" \"\\n\""); 121 break; 122 case 'D': 123 odprecede(); 124 add("4/4 \" %010u \" \"\\n\""); 125 break; 126 case 'e': /* undocumented in od */ 127 case 'F': 128 odprecede(); 129 add("2/8 \" %21.14e \" \"\\n\""); 130 break; 131 132 case 'f': 133 odprecede(); 134 add("4/4 \" %14.7e \" \"\\n\""); 135 break; 136 case 'H': 137 case 'X': 138 odprecede(); 139 add("4/4 \" %08x \" \"\\n\""); 140 break; 141 case 'h': 142 case 'x': 143 odprecede(); 144 add("8/2 \" %04x \" \"\\n\""); 145 break; 146 case 'I': 147 case 'L': 148 case 'l': 149 odprecede(); 150 add("4/4 \" %11d \" \"\\n\""); 151 break; 152 case 'i': 153 odprecede(); 154 add("8/2 \" %6d \" \"\\n\""); 155 break; 156 case 'O': 157 odprecede(); 158 add("4/4 \" %011o \" \"\\n\""); 159 break; 160 case 't': 161 for (ch = 0; optarg[ch]; ) { 162 odprecede(); 163 switch (optarg[ch]) { 164 case 'a': 165 ch++; 166 add("16/1 \"%3_u \" \"\\n\""); 167 break; 168 case 'c': 169 ch++; 170 add("16/1 \"%3_c \" \"\\n\""); 171 break; 172 case 'f': 173 ch++; 174 if (optarg[ch] == 'F' || 175 optarg[ch] == '4') { 176 ch++; 177 add("4/4 \" %14.7e\" \"\\n\""); 178 } 179 else if (optarg[ch] == 'L' || 180 optarg[ch] == '8') { 181 ch++; 182 add("2/8 \" %16.14e\" \"\\n\""); 183 } 184 else if (optarg[ch] == 'D') 185 /* long doubles vary in size */ 186 usage(); 187 else 188 add("2/8 \" %16.14e\" \"\\n\""); 189 break; 190 case 'd': 191 x = 0; 192 goto extensions; 193 case 'o': 194 x = 1; 195 goto extensions; 196 case 'u': 197 x = 2; 198 goto extensions; 199 case 'x': 200 x = 3; 201 extensions: 202 ch++; 203 y = 2; 204 if (optarg[ch] == 'C' || 205 optarg[ch] == '1') { 206 ch++; 207 y = 0; 208 } 209 else if (optarg[ch] == 'S' || 210 optarg[ch] == '2') { 211 ch++; 212 y = 1; 213 } 214 else if (optarg[ch] == 'I' || 215 optarg[ch] == '4') { 216 ch++; 217 y = 2; 218 } 219 else if (optarg[ch] == 'L' || 220 optarg[ch] == '8') { 221 ch++; 222 y = 3; 223 } 224 add(fmt[x][y]); 225 break; 226 default: 227 usage(); 228 } 229 } 230 break; 231 case 'v': 232 vflag = ALL; 233 break; 234 case 'P': 235 case 'p': 236 case 's': 237 case 'w': 238 case '?': 239 default: 240 warnx("od(1) has been deprecated for hexdump(1)."); 241 if (ch != '?') 242 warnx( 243 "hexdump(1) compatibility doesn't support the -%c option%s\n", 244 ch, ch == 's' ? "; see strings(1)." : "."); 245 usage(); 246 } 247 248 if (!fshead) { 249 add("\"%07.7_Ao\n\""); 250 add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); 251 } 252 253 argc -= optind; 254 *argvp += optind; 255 256 if (argc) 257 odoffset(argc, argvp); 258 } 259 260 static void 261 odoffset(argc, argvp) 262 int argc; 263 char ***argvp; 264 { 265 char *num, *p; 266 int base; 267 char *end; 268 269 /* 270 * The offset syntax of od(1) was genuinely bizarre. First, if 271 * it started with a plus it had to be an offset. Otherwise, if 272 * there were at least two arguments, a number or lower-case 'x' 273 * followed by a number makes it an offset. By default it was 274 * octal; if it started with 'x' or '0x' it was hex. If it ended 275 * in a '.', it was decimal. If a 'b' or 'B' was appended, it 276 * multiplied the number by 512 or 1024 byte units. There was 277 * no way to assign a block count to a hex offset. 278 * 279 * We assume it's a file if the offset is bad. 280 */ 281 p = argc == 1 ? (*argvp)[0] : (*argvp)[1]; 282 if (!p) 283 return; 284 285 if (*p != '+' && (argc < 2 || 286 (!isdigit((unsigned char)p[0]) && 287 (p[0] != 'x' || !isxdigit((unsigned char)p[1]))))) 288 return; 289 290 base = 0; 291 /* 292 * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and 293 * set base. 294 */ 295 if (p[0] == '+') 296 ++p; 297 if (p[0] == 'x' && isxdigit((unsigned char)p[1])) { 298 ++p; 299 base = 16; 300 } else if (p[0] == '0' && p[1] == 'x') { 301 p += 2; 302 base = 16; 303 } 304 305 /* skip over the number */ 306 if (base == 16) 307 for (num = p; isxdigit((unsigned char)*p); ++p); 308 else 309 for (num = p; isdigit((unsigned char)*p); ++p); 310 311 /* check for no number */ 312 if (num == p) 313 return; 314 315 /* if terminates with a '.', base is decimal */ 316 if (*p == '.') { 317 if (base) 318 return; 319 base = 10; 320 } 321 322 skip = strtol(num, &end, base ? base : 8); 323 324 /* if end isn't the same as p, we got a non-octal digit */ 325 if (end != p) { 326 skip = 0; 327 return; 328 } 329 330 if (*p) { 331 if (*p == 'B') { 332 skip *= 1024; 333 ++p; 334 } else if (*p == 'b') { 335 skip *= 512; 336 ++p; 337 } 338 } 339 if (*p) { 340 skip = 0; 341 return; 342 } 343 /* 344 * If the offset uses a non-octal base, the base of the offset 345 * is changed as well. This isn't pretty, but it's easy. 346 */ 347 #define TYPE_OFFSET 7 348 if (base == 16) { 349 fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; 350 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; 351 } else if (base == 10) { 352 fshead->nextfu->fmt[TYPE_OFFSET] = 'd'; 353 fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd'; 354 } 355 356 /* Terminate file list. */ 357 (*argvp)[1] = NULL; 358 } 359 360 static void 361 odprecede() 362 { 363 static int first = 1; 364 365 if (first) { 366 first = 0; 367 add("\"%07.7_Ao\n\""); 368 add("\"%07.7_ao \""); 369 } else 370 add("\" \""); 371 } 372