]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/xd.c
cpu: make -p work with explicit service in dialstring (same as import)
[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 void
62 main(int argc, char *argv[])
63 {
64         int i, err;
65         Arg *ap;
66
67         Binit(&bout, 1, OWRITE);
68         Blethal(&bout, nil);
69         err = 0;
70         ap = 0;
71         while(argc>1 && argv[1][0]=='-' && argv[1][1]){
72                 --argc;
73                 argv++;
74                 argv[0]++;
75                 if(argv[0][0] == 'r'){
76                         repeats = 1;
77                         if(argv[0][1])
78                                 goto Usage;
79                         continue;
80                 }
81                 if(argv[0][0] == 's'){
82                         le = 1;
83                         if(argv[0][1])
84                                 goto Usage;
85                         continue;
86                 }
87                 if(argv[0][0] == 'u'){
88                         flush = 1;
89                         if(argv[0][1])
90                                 goto Usage;
91                         continue;
92                 }
93                 if(argv[0][0] == 'a'){
94                         argv[0]++;
95                         switch(argv[0][0]){
96                         case 'o':
97                                 abase = 0;
98                                 break;
99                         case 'd':
100                                 abase = 1;
101                                 break;
102                         case 'x':
103                                 abase = 2;
104                                 break;
105                         default:
106                                 goto Usage;
107                         }
108                         if(argv[0][1])
109                                 goto Usage;
110                         continue;
111                 }
112                 ap = &arg[narg];
113                 initarg();
114                 while(argv[0][0]){
115                         switch(argv[0][0]){
116                         case 'c':
117                                 ap->ascii = 1;
118                                 ap->loglen = 0;
119                                 if(argv[0][1] || argv[0][-1]!='-')
120                                         goto Usage;
121                                 break;
122                         case 'o':
123                                 ap->base = 0;
124                                 break;
125                         case 'd':
126                                 ap->base = 1;
127                                 break;
128                         case 'x':
129                                 ap->base = 2;
130                                 break;
131                         case 'b':
132                         case '1':
133                                 ap->loglen = 0;
134                                 break;
135                         case 'w':
136                         case '2':
137                                 ap->loglen = 1;
138                                 break;
139                         case 'l':
140                         case '4':
141                                 ap->loglen = 2;
142                                 break;
143                         case 'v':
144                         case '8':
145                                 ap->loglen = 3;
146                                 break;
147                         default:
148                         Usage:
149    fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");
150                                 exits("usage");
151                         }
152                         argv[0]++;
153                 }
154                 if(ap->ascii)
155                         ap->fn = fmtc;
156                 else
157                         ap->fn = fmt[ap->loglen];
158                 ap->fmt = dfmt[ap->loglen][ap->base];
159                 ap->afmt = afmt[ap>arg][abase];
160         }
161         if(narg == 0)
162                 initarg();
163         if(argc == 1)
164                 err = xd(0, 0);
165         else if(argc == 2)
166                 err = xd(argv[1], 0);
167         else for(i=1; i<argc; i++)
168                 err |= xd(argv[i], 1);
169         exits(err? "error" : 0);
170 }
171
172 void
173 initarg(void)
174 {
175         Arg *ap;
176
177         ap = &arg[narg++];
178         if(narg >= Narg){
179                 fprint(2, "xd: too many formats (max %d)\n", Narg);
180                 exits("usage");
181         }
182         ap->ascii = 0;
183         ap->loglen = 2;
184         ap->base = 2;
185         ap->fn = fmt2;
186         ap->fmt = dfmt[ap->loglen][ap->base];
187         ap->afmt = afmt[narg>1][abase];
188 }
189
190 int
191 xd(char *name, int title)
192 {
193         int fd;
194         int i, star;
195         Arg *ap;
196         Biobuf *bp;
197
198         fd = 0;
199         if(name){
200                 bp = Bopen(name, OREAD);
201                 if(bp == 0){
202                         fprint(2, "xd: can't open %s\n", name);
203                         return 1;
204                 }
205         }else{
206                 bp = &bin;
207                 Binit(bp, fd, OREAD);
208         }
209         Blethal(bp, nil);
210         if(title)
211                 xprint("%s\n", name);
212         addr = 0;
213         star = 0;
214         while((ndata=Bread(bp, data, 16)) >= 0){
215                 if(ndata < 16)
216                         for(i=ndata; i<16; i++)
217                                 data[i] = 0;
218                 if(ndata==16 && repeats){
219                         if(addr>0 && data[0]==odata[0]){
220                                 for(i=1; i<16; i++)
221                                         if(data[i] != odata[i])
222                                                 break;
223                                 if(i == 16){
224                                         addr += 16;
225                                         if(star == 0){
226                                                 star++;
227                                                 xprint("*\n", 0);
228                                         }
229                                         continue;
230                                 }
231                         }
232                         for(i=0; i<16; i++)
233                                 odata[i] = data[i];
234                         star = 0;
235                 }
236                 for(ap=arg; ap<&arg[narg]; ap++){
237                         xprint(ap->afmt, addr);
238                         (*ap->fn)(ap->fmt);
239                         xprint("\n", 0);
240                         if(flush)
241                                 Bflush(&bout);
242                 }
243                 addr += ndata;
244                 if(ndata<16){
245                         xprint(afmt[0][abase], addr);
246                         xprint("\n", 0);
247                         if(flush)
248                                 Bflush(&bout);
249                         break;
250                 }
251         }
252         Bterm(bp);
253         return 0;
254 }
255
256 void
257 fmt0(char *f)
258 {
259         int i;
260         for(i=0; i<ndata; i++)
261                 xprint(f, data[i]);
262 }
263
264 void
265 fmt1(char *f)
266 {
267         int i;
268         for(i=0; i<ndata; i+=sizeof(unsigned short))
269                 xprint(f, le ? (data[i+1]<<8)|data[i]
270                              : (data[i]<<8)|data[i+1]);
271 }
272
273 void
274 fmt2(char *f)
275 {
276         int i;
277         for(i=0; i<ndata; i+=sizeof(unsigned long))
278                 xprint(f, le ? (data[i+3]<<24)|(data[i+2]<<16)|(data[i+1]<<8)|data[i]
279                              : (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]);
280 }
281
282 void
283 fmt3(char *f)
284 {
285         int i;
286         unsigned long long v;
287         for(i=0; i<ndata; i+=sizeof(unsigned long long)){
288                 if(le){
289                         v = (data[i+3+4]<<24)|(data[i+2+4]<<16)|(data[i+1+4]<<8)|data[i+4];
290                         v <<= 32;
291                         v |= (data[i+3]<<24)|(data[i+2]<<16)|(data[i+1]<<8)|data[i];
292                 }else{
293                         v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];
294                         v <<= 32;
295                         v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];
296                 }
297                 if(Bprint(&bout, f, v)<0){
298                         fprint(2, "xd: i/o error\n");
299                         exits("i/o error");
300                 }
301         }
302 }
303
304 void
305 fmtc(char *f)
306 {
307         int i;
308
309         USED(f);
310         for(i=0; i<ndata; i++)
311                 switch(data[i]){
312                 case '\t':
313                         xprint(cfmt[1][2], "\\t");
314                         break;
315                 case '\r':
316                         xprint(cfmt[1][2], "\\r");
317                         break;
318                 case '\n':
319                         xprint(cfmt[1][2], "\\n");
320                         break;
321                 case '\b':
322                         xprint(cfmt[1][2], "\\b");
323                         break;
324                 default:
325                         if(data[i]>=0x7F || ' '>data[i])
326                                 xprint(cfmt[2][2], data[i]);
327                         else
328                                 xprint(cfmt[0][2], data[i]);
329                         break;
330                 }
331 }
332
333 void
334 xprint(char *fmt, ...)
335 {
336         va_list arglist;
337
338         va_start(arglist, fmt);
339         if(Bvprint(&bout, fmt, arglist)<0){
340                 fprint(2, "xd: i/o error\n");
341                 exits("i/o error");
342         }
343         va_end(arglist);
344 }