]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/xd.c
libaml: fix gc bug, need to amltake()/amldrop() temporary buffer
[plan9front.git] / sys / src / cmd / xd.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 unsigned char   odata[16];
6 unsigned char   data[16];
7 int             ndata;
8 unsigned long   addr;
9 int             repeats;
10 int             le;     /* little endian */
11 int             flush;
12 int             abase=2;
13 int             xd(char *, int);
14 void            xprint(char *, ...);
15 void            initarg(void), swizz(void);
16 enum{
17         Narg=10
18 };
19 typedef struct Arg Arg;
20 typedef void fmtfn(char *);
21 struct Arg
22 {
23         int     ascii;          /* 0==none, 1==ascii */
24         int     loglen;         /* 0==1, 1==2, 2==4, 3==8 */
25         int     base;           /* 0==8, 1==10, 2==16 */
26         fmtfn   *fn;            /* function to call with data */
27         char    *afmt;          /* format to use to print address */
28         char    *fmt;           /* format to use to print data */
29 }arg[Narg];
30 int     narg;
31
32 fmtfn   fmt0, fmt1, fmt2, fmt3, fmtc;
33 fmtfn *fmt[4] = {
34         fmt0,
35         fmt1,
36         fmt2,
37         fmt3
38 };
39
40 char *dfmt[4][3] = {
41         " %.3uo",       " %.3ud",       " %.2ux",
42         " %.6uo",       " %.5ud",       " %.4ux",
43         " %.11luo",     " %.10lud",     " %.8lux",
44         " %.22lluo",    " %.20llud",    " %.16llux",
45 };
46
47 char *cfmt[3][3] = {
48         "   %c",        "   %c",        "  %c",
49         " %.3s",        " %.3s",        " %.2s",
50         " %.3uo",       " %.3ud",       " %.2ux",
51 };
52
53 char *afmt[2][3] = {
54         "%.7luo ",      "%.7lud ",      "%.7lux ",
55         "%7luo ",       "%7lud ",       "%7lux ",
56 };
57
58 Biobuf  bin;
59 Biobuf  bout;
60
61 int
62 flushout(Biobufhdr *bp, void *v, long n)
63 {
64         Bflush(&bout);
65         return read(bp->fid, v, n);
66 }
67
68 void
69 main(int argc, char *argv[])
70 {
71         int i, err;
72         Arg *ap;
73
74         Binit(&bout, 1, OWRITE);
75         Blethal(&bout, nil);
76         err = 0;
77         ap = 0;
78         while(argc>1 && argv[1][0]=='-' && argv[1][1]){
79                 --argc;
80                 argv++;
81                 argv[0]++;
82                 if(argv[0][0] == 'r'){
83                         repeats = 1;
84                         if(argv[0][1])
85                                 goto Usage;
86                         continue;
87                 }
88                 if(argv[0][0] == 's'){
89                         le = 1;
90                         if(argv[0][1])
91                                 goto Usage;
92                         continue;
93                 }
94                 if(argv[0][0] == 'u'){
95                         flush = 1;
96                         if(argv[0][1])
97                                 goto Usage;
98                         continue;
99                 }
100                 if(argv[0][0] == 'a'){
101                         argv[0]++;
102                         switch(argv[0][0]){
103                         case 'o':
104                                 abase = 0;
105                                 break;
106                         case 'd':
107                                 abase = 1;
108                                 break;
109                         case 'x':
110                                 abase = 2;
111                                 break;
112                         default:
113                                 goto Usage;
114                         }
115                         if(argv[0][1])
116                                 goto Usage;
117                         continue;
118                 }
119                 ap = &arg[narg];
120                 initarg();
121                 while(argv[0][0]){
122                         switch(argv[0][0]){
123                         case 'c':
124                                 ap->ascii = 1;
125                                 ap->loglen = 0;
126                                 if(argv[0][1] || argv[0][-1]!='-')
127                                         goto Usage;
128                                 break;
129                         case 'o':
130                                 ap->base = 0;
131                                 break;
132                         case 'd':
133                                 ap->base = 1;
134                                 break;
135                         case 'x':
136                                 ap->base = 2;
137                                 break;
138                         case 'b':
139                         case '1':
140                                 ap->loglen = 0;
141                                 break;
142                         case 'w':
143                         case '2':
144                                 ap->loglen = 1;
145                                 break;
146                         case 'l':
147                         case '4':
148                                 ap->loglen = 2;
149                                 break;
150                         case 'v':
151                         case '8':
152                                 ap->loglen = 3;
153                                 break;
154                         default:
155                         Usage:
156    fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");
157                                 exits("usage");
158                         }
159                         argv[0]++;
160                 }
161                 if(ap->ascii)
162                         ap->fn = fmtc;
163                 else
164                         ap->fn = fmt[ap->loglen];
165                 ap->fmt = dfmt[ap->loglen][ap->base];
166                 ap->afmt = afmt[ap>arg][abase];
167         }
168         if(narg == 0)
169                 initarg();
170         if(argc == 1)
171                 err = xd(0, 0);
172         else if(argc == 2)
173                 err = xd(argv[1], 0);
174         else for(i=1; i<argc; i++)
175                 err |= xd(argv[i], 1);
176         exits(err? "error" : 0);
177 }
178
179 void
180 initarg(void)
181 {
182         Arg *ap;
183
184         ap = &arg[narg++];
185         if(narg >= Narg){
186                 fprint(2, "xd: too many formats (max %d)\n", Narg);
187                 exits("usage");
188         }
189         ap->ascii = 0;
190         ap->loglen = 2;
191         ap->base = 2;
192         ap->fn = fmt2;
193         ap->fmt = dfmt[ap->loglen][ap->base];
194         ap->afmt = afmt[narg>1][abase];
195 }
196
197 int
198 xd(char *name, int title)
199 {
200         int fd;
201         int i, star;
202         Arg *ap;
203         Biobuf *bp;
204
205         fd = 0;
206         if(name){
207                 bp = Bopen(name, OREAD);
208                 if(bp == 0){
209                         fprint(2, "xd: can't open %s\n", name);
210                         return 1;
211                 }
212         }else{
213                 bp = &bin;
214                 Binit(bp, fd, OREAD);
215         }
216         if(flush) Biofn(bp, flushout);
217         Blethal(bp, nil);
218         if(title)
219                 xprint("%s\n", name);
220         addr = 0;
221         star = 0;
222         while((ndata=Bread(bp, data, 16)) >= 0){
223                 if(ndata < 16)
224                         for(i=ndata; i<16; i++)
225                                 data[i] = 0;
226                 if(ndata==16 && repeats){
227                         if(addr>0 && data[0]==odata[0]){
228                                 for(i=1; i<16; i++)
229                                         if(data[i] != odata[i])
230                                                 break;
231                                 if(i == 16){
232                                         addr += 16;
233                                         if(star == 0){
234                                                 star++;
235                                                 xprint("*\n", 0);
236                                         }
237                                         continue;
238                                 }
239                         }
240                         for(i=0; i<16; i++)
241                                 odata[i] = data[i];
242                         star = 0;
243                 }
244                 for(ap=arg; ap<&arg[narg]; ap++){
245                         xprint(ap->afmt, addr);
246                         (*ap->fn)(ap->fmt);
247                         xprint("\n", 0);
248                 }
249                 addr += ndata;
250                 if(ndata<16){
251                         xprint(afmt[0][abase], addr);
252                         xprint("\n", 0);
253                         break;
254                 }
255         }
256         Bterm(bp);
257         return 0;
258 }
259
260 void
261 fmt0(char *f)
262 {
263         int i;
264         for(i=0; i<ndata; i++)
265                 xprint(f, data[i]);
266 }
267
268 void
269 fmt1(char *f)
270 {
271         int i;
272         for(i=0; i<ndata; i+=sizeof(unsigned short))
273                 xprint(f, le ? (data[i+1]<<8)|data[i]
274                              : (data[i]<<8)|data[i+1]);
275 }
276
277 void
278 fmt2(char *f)
279 {
280         int i;
281         for(i=0; i<ndata; i+=sizeof(unsigned long))
282                 xprint(f, le ? (data[i+3]<<24)|(data[i+2]<<16)|(data[i+1]<<8)|data[i]
283                              : (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]);
284 }
285
286 void
287 fmt3(char *f)
288 {
289         int i;
290         unsigned long long v;
291         for(i=0; i<ndata; i+=sizeof(unsigned long long)){
292                 if(le){
293                         v = (data[i+3+4]<<24)|(data[i+2+4]<<16)|(data[i+1+4]<<8)|data[i+4];
294                         v <<= 32;
295                         v |= (data[i+3]<<24)|(data[i+2]<<16)|(data[i+1]<<8)|data[i];
296                 }else{
297                         v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];
298                         v <<= 32;
299                         v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];
300                 }
301                 if(Bprint(&bout, f, v)<0){
302                         fprint(2, "xd: i/o error\n");
303                         exits("i/o error");
304                 }
305         }
306 }
307
308 void
309 fmtc(char *f)
310 {
311         int i;
312
313         USED(f);
314         for(i=0; i<ndata; i++)
315                 switch(data[i]){
316                 case '\t':
317                         xprint(cfmt[1][2], "\\t");
318                         break;
319                 case '\r':
320                         xprint(cfmt[1][2], "\\r");
321                         break;
322                 case '\n':
323                         xprint(cfmt[1][2], "\\n");
324                         break;
325                 case '\b':
326                         xprint(cfmt[1][2], "\\b");
327                         break;
328                 default:
329                         if(data[i]>=0x7F || ' '>data[i])
330                                 xprint(cfmt[2][2], data[i]);
331                         else
332                                 xprint(cfmt[0][2], data[i]);
333                         break;
334                 }
335 }
336
337 void
338 xprint(char *fmt, ...)
339 {
340         va_list arglist;
341
342         va_start(arglist, fmt);
343         if(Bvprint(&bout, fmt, arglist)<0){
344                 fprint(2, "xd: i/o error\n");
345                 exits("i/o error");
346         }
347         va_end(arglist);
348 }