mkfs, mkproto: minor improvements
[minix.git] / commands / od / od.c
blob1a2a2bb88825eda50174ea175a74dab2e77e14b7
1 /* od - octal dump Author: Andy Tanenbaum */
3 #include <sys/types.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <stdio.h>
10 int bflag, cflag, dflag, oflag, xflag, hflag, vflag;
11 int linenr, width, state, ever;
12 int prevwds[8];
13 long off;
14 char buf[512], buffer[BUFSIZ];
15 int next;
16 int bytespresent;
18 int main(int argc, char **argv);
19 long offset(int argc, char *argv [], int k);
20 void dumpfile(void);
21 void wdump(short *words, int k, int radix);
22 void bdump(char bytes [16 ], int k, int c);
23 void byte(int val, int c);
24 int getwords(short **words);
25 int same(short *w1, int *w2);
26 void outword(int val, int radix);
27 void outnum(int num, int radix);
28 void addrout(long l);
29 char hexit(int k);
30 void usage(void);
32 int main(argc, argv)
33 int argc;
34 char *argv[];
36 int k, flags;
37 char *p;
39 /* Process flags */
40 setbuf(stdout, buffer);
41 flags = 0;
42 p = argv[1];
43 if (argc > 1 && *p == '-') {
44 /* Flags present. */
45 flags++;
46 p++;
47 while (*p) {
48 switch (*p) {
49 case 'b': bflag++; break;
50 case 'c': cflag++; break;
51 case 'd': dflag++; break;
52 case 'h': hflag++; break;
53 case 'o': oflag++; break;
54 case 'v': vflag++; break;
55 case 'x': xflag++; break;
56 default: usage();
58 p++;
60 } else {
61 oflag = 1;
63 if ((bflag | cflag | dflag | oflag | xflag) == 0) oflag = 1;
64 k = (flags ? 2 : 1);
65 if (bflag | cflag) {
66 width = 8;
67 } else if (oflag) {
68 width = 7;
69 } else if (dflag) {
70 width = 6;
71 } else {
72 width = 5;
75 /* Process file name, if any. */
76 p = argv[k];
77 if (k < argc && *p != '+') {
78 /* Explicit file name given. */
79 close(0);
80 if (open(argv[k], O_RDONLY) != 0) {
81 fprintf(stderr, "od: cannot open %s\n", argv[k]);
82 exit(1);
84 k++;
87 /* Process offset, if any. */
88 if (k < argc) {
89 /* Offset present. */
90 off = offset(argc, argv, k);
91 off = (off / 16L) * 16L;
92 lseek(0, off, SEEK_SET);
94 dumpfile();
95 addrout(off);
96 printf("\n");
97 return(0);
101 long offset(argc, argv, k)
102 int argc;
103 char *argv[];
104 int k;
106 int dot, radix;
107 char *p, c;
108 long val;
110 /* See if the offset is decimal. */
111 dot = 0;
112 p = argv[k];
113 while (*p)
114 if (*p++ == '.') dot = 1;
116 /* Convert offset to binary. */
117 radix = (dot ? 10 : 8);
118 val = 0;
119 p = argv[k];
120 if (*p == '+') p++;
121 while (*p != 0 && *p != '.') {
122 c = *p++;
123 if (c < '0' || c > '9') {
124 printf("Bad character in offset: %c\n", c);
125 exit(1);
127 val = radix * val + c - '0';
130 p = argv[k + 1];
131 if (k + 1 == argc - 1 && *p == 'b') val = 512L * val;
132 return(val);
136 void dumpfile()
138 int k;
139 short *words;
141 while ((k = getwords(&words))) { /* 'k' is # bytes read */
142 if (!vflag) { /* ensure 'lazy' evaluation */
143 if (k == 16 && ever == 1 && same(words, prevwds)) {
144 if (state == 0) {
145 printf("*\n");
146 state = 1;
147 off += 16;
148 continue;
149 } else if (state == 1) {
150 off += 16;
151 continue;
155 addrout(off);
156 off += k;
157 state = 0;
158 ever = 1;
159 linenr = 1;
160 if (oflag) wdump(words, k, 8);
161 if (dflag) wdump(words, k, 10);
162 if (xflag) wdump(words, k, 16);
163 if (cflag) bdump((char *)words, k, (int)'c');
164 if (bflag) bdump((char *)words, k, (int)'b');
165 for (k = 0; k < 8; k++) prevwds[k] = words[k];
166 for (k = 0; k < 8; k++) words[k] = 0;
171 void wdump(words, k, radix)
172 short *words;
173 int k, radix;
175 int i;
177 if (linenr++ != 1) printf(" ");
178 for (i = 0; i < (k + 1) / 2; i++) outword(words[i] & 0xFFFF, radix);
179 printf("\n");
183 void bdump(bytes, k, c)
184 char bytes[16];
185 int k;
186 char c;
188 int i;
190 if (linenr++ != 1) printf(" ");
191 for (i = 0; i < k; i++) byte(bytes[i] & 0377, c);
192 printf("\n");
195 void byte(val, c)
196 int val;
197 char c;
199 if (c == 'b') {
200 printf(" ");
201 outnum(val, 7);
202 return;
204 if (val == 0)
205 printf(" \\0");
206 else if (val == '\b')
207 printf(" \\b");
208 else if (val == '\f')
209 printf(" \\f");
210 else if (val == '\n')
211 printf(" \\n");
212 else if (val == '\r')
213 printf(" \\r");
214 else if (val == '\t')
215 printf(" \\t");
216 else if (val >= ' ' && val < 0177)
217 printf(" %c", val);
218 else {
219 printf(" ");
220 outnum(val, 7);
225 int getwords(words)
226 short **words;
228 int count;
230 if (next >= bytespresent) {
231 bytespresent = read(0, buf, 512);
232 next = 0;
234 if (next >= bytespresent) return(0);
235 *words = (short *) &buf[next];
236 if (next + 16 <= bytespresent)
237 count = 16;
238 else
239 count = bytespresent - next;
241 next += count;
242 return(count);
245 int same(w1, w2)
246 short *w1;
247 int *w2;
249 int i;
250 i = 8;
251 while (i--)
252 if (*w1++ != *w2++) return(0);
253 return(1);
256 void outword(val, radix)
257 int val, radix;
259 /* Output 'val' in 'radix' in a field of total size 'width'. */
261 int i;
263 if (radix == 16) i = width - 4;
264 if (radix == 10) i = width - 5;
265 if (radix == 8) i = width - 6;
266 if (i == 1)
267 printf(" ");
268 else if (i == 2)
269 printf(" ");
270 else if (i == 3)
271 printf(" ");
272 else if (i == 4)
273 printf(" ");
274 outnum(val, radix);
278 void outnum(num, radix)
279 int num, radix;
281 /* Output a number with all leading 0s present. Octal is 6 places,
282 * decimal is 5 places, hex is 4 places.
284 unsigned val;
286 val = (unsigned) num;
287 if (radix == 8)
288 printf ("%06o", val);
289 else if (radix == 10)
290 printf ("%05u", val);
291 else if (radix == 16)
292 printf ("%04x", val);
293 else if (radix == 7) {
294 /* special case */
295 printf ("%03o", val);
300 void addrout(l)
301 long l;
303 if (hflag == 0) {
304 printf("%07lo", l);
305 } else {
306 printf("%07lx", l);
311 void usage()
313 fprintf(stderr, "Usage: od [-bcdhovx] [file] [ [+] offset [.] [b] ]\n");