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