xd.c 5.6 KB

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