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
oldsyntax(argc,argvp)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
odoffset(argc,argvp)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
odprecede()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