/* Copyright (C)1999 ASH multimedia lab. (http://ash.jp/) */ /************************/ /* 16進ダンプコマンド */ /************************/ #include #include #include #include "libfile.h" #include "libstr.h" #define MAXBUF 65535 #define MAXSTR 1024 char prog_name[64]; /* 使用方法の表示 */ usage() { printf("Usage: %s [-l] [-2] [-w width] files\n", prog_name); printf(" -j: 入力文字コード(JIS)\n"); printf(" -s: 入力文字コード(SJIS)\n"); printf(" -e: 入力文字コード(EUC)\n"); printf(" -l: ラインモード\n"); printf(" -2: 2行モード\n"); printf(" -w: 表示幅\n"); printf(" files: ファイル名\n"); exit(-1); } /* メイン処理 */ main(argc, argv) int argc; char *argv[]; { int lmode = 0; /* ラインモード(OFF) */ int dmode = 0; /* 2行モード(OFF) */ int code = CD_EUC; /* 文字コード(EUC) */ int width = 16; /* 表示幅 */ int rtn; FILE *fp; /* オプションの解析 */ while ((rtn = getopt(argc, argv, "xjsel2w:")) != -1) { switch(rtn) { /* オプション解析 */ case 'j': /* '-j' option (JIS code) */ code = CD_JIS; break; case 's': /* '-s' option (SJIS code) */ code = CD_SJIS; break; case 'e': /* '-e' option (EUC code) */ code = CD_EUC; break; case 'l': /* '-l' option (Line mode) */ lmode = 1; /* ラインモード */ break; case '2': /* '-2' option (2 line mode) */ dmode = 1; /* 2行モード */ break; case 'w': /* '-w' option (Width) */ width = atoi(optarg); break; default: /* 使用方法の表示 */ usage(); } } if (width < 1) {width = 16;} /* 表示幅 */ /* 入力ファイルのオープン */ if (argv[optind] != NULL) { for (; argv[optind]; optind++) { if (isdir(argv[optind])) {continue;} printf ("%s\n", argv[optind]); fp = fopen (argv[optind], "r"); if (!fp) { printf ("File open error\n"); exit(1); } if (lmode) { /* 行モード */ linedump(code, fp, width, dmode); } else { /* バイトモード */ bytedump(code, fp, width, dmode); } fclose(fp); } } else { /* 指定なしの場合、標準入力 */ if (lmode) { /* 行モード */ linedump(code, stdin, width, dmode); } else { /* バイトモード */ bytedump(code, stdin, width, dmode); } } } /****************************/ /* 行モード16進ダンプ処理 */ /****************************/ linedump(code, fp, width, dmode) int code; /* 文字コード (i) */ /* CD_JIS,CD_SJIS,CD_EUC,CD_UTF8,CD_UTF16 */ FILE *fp; /* ファイルハンドル */ int width; /* 表示幅 (i) */ int dmode; /* 対応表示モード (i) */ { char buf[MAXBUF+1]; int len; int mode = JIS_ROMA; int wsize, split; int skip = 0; int line; int b; if (dmode) { wsize = 3; /* 1バイトを3桁で表示 */ split = 0; /* 等間隔で表示 */ } else { wsize = 1; /* 1バイトを1桁で表示 */ split = 8; /* 8バイト単位で表示 */ } for (line = 1; ; line++) { if (!fgets(buf, MAXBUF, fp)) {break;} len = strlen(buf); if (ferror(fp)) { perror("Read error"); exit(1); } for (b = 0; b < len; b += width) { /* 行番号の表示 */ if (b) {printf("--------: ");} else {printf("%08d: ", line);} /* 16進ダンプの表示 */ dmp_hex(code, buf, len, b, width, split); if (dmode) { printf("\n : "); } else { printf(" :"); } /* キャラクタダンプの表示 */ dmp_char(code, buf, len, b, width, wsize, &mode, &skip); printf("\n"); } } } /********************************/ /* バイトモード16進ダンプ処理 */ /********************************/ bytedump(code, fp, width, dmode) int code; /* 文字コード */ /* CD_JIS,CD_SJIS,CD_EUC,CD_UTF8,CD_UTF16 */ FILE *fp; /* ファイルハンドル */ int width; /* 表示幅 */ int dmode; /* 対応表示モード (i) */ { struct tbuf cbuf; int len; int mode = JIS_ROMA; int wsize, split; int skip = 0; int b; if (dmode) { wsize = 3; /* 1バイトを3桁で表示 */ split = 0; /* 等間隔で表示 */ } else { wsize = 1; /* 1バイトを1桁で表示 */ split = 8; /* 8バイト単位で表示 */ } open_buf(&cbuf, width, 4); for (b = 0; len = get_buf(&cbuf, fp); b += width) { /* バイト数の表示 */ printf("%08x: ", b); /* 16進ダンプの表示 */ dmp_hex(code, cbuf.dat, len, 0, width, split); if (dmode) { printf("\n : "); } else { printf(" :"); } /* キャラクタダンプの表示 */ dmp_char(code, cbuf.dat, len, 0, width, wsize, &mode, &skip); printf("\n"); } } /********************/ /* 16進ダンプの表示 */ /********************/ dmp_hex(code, str, len, sta, width, split) int code; /* 文字コード (i) */ /* CD_JIS,CD_SJIS,CD_EUC,CD_UTF8,CD_UTF16 */ char *str; /* 文字列 (i) */ int len; /* 文字列長 (i) */ int sta; /* 表示開始バイト位置 (i) */ int width; /* 表示幅 (i) 0:等間隔 8:8バイト単位で表示 */ int split; /* 表示分離幅 (i) */ { int idx; for (idx = sta; idx < sta + width; idx++) { /* バイト区切りの表示 */ if (idx != sta) { if (split > 0) { if ((idx - sta) % split) {printf(" ");} else {printf(" ");} } else { printf(" "); } } /* 16進コードの表示 */ if (idx >= len) { printf("--"); } else { printf("%02x", (unsigned char)str[idx]); } } } /**************************/ /* キャラクタダンプの表示 */ /**************************/ dmp_char(code, str, len, sta, width, wsize, mode, skip) int code; /* 文字コード (i) */ /* CD_JIS,CD_SJIS,CD_EUC,CD_UTF8,CD_UTF16 */ char *str; /* 文字列 (i) */ int len; /* 文字列長 (i) */ int sta; /* 表示開始バイト位置 (i) */ int width; /* 表示幅 (i) */ int wsize; /* 1桁の表示幅 (i) 1:通常 3:byte対応 */ int *mode; /* JIS文字モード (i/o) */ /* JIS_CTRL,JIS_ROMA,JIS_KANA,JIS_KNJI,JIS_HOJO */ int *skip; /* スキップバイト数 (i/o) */ { int byte; /* バイト数 */ int keta; /* 表示桁数 */ int kind; /* 文字の種類 */ /* CH_BIN,CH_CTRL,CH_ROMA,CH_KANA,CH_KNJI,CH_HOJO */ int idx, i; unsigned char cdisp[9]; for (idx = sta; idx < sta + width; idx += byte) { if (idx >= len) {break;} /* バイト区切りの表示 */ if (idx != sta) { if (wsize > 1) {printf(" ");} } /* 先頭文字のスキップ処理(2バイト目以降の場合) */ if (*skip > 0) { if (wsize > 1) { for (i = 0; i < *skip * wsize - 1; i++) {printf(" ");} } else { for (i = 0; i < *skip; i++) {printf(" ");} } byte = *skip; *skip = 0; continue; } /* 文字の判定 */ judge_char(code, mode, str, len, idx, &byte, &keta, &kind); /* 文字の表示 */ switch (kind) { case CH_CTRL: printf("_"); break; case CH_ROMA: printf("%c", str[idx]); break; case CH_KANA: case CH_KNJI: if (code == CD_JIS) { jis2euc((unsigned char *)&str[idx], cdisp); printf("%s", cdisp); } else if (code == CD_SJIS) { sjis2euc((unsigned char *)&str[idx], cdisp); printf("%s", cdisp); } else { for (i = 0; i < byte; i++) {printf("%c", str[idx+i]);} } break; default: printf("@"); } /* 表示幅あふれの計算 */ *skip = idx - sta + byte - width; if (*skip > 0) {break;} else {*skip = 0;} /* 空白の表示 */ if (wsize > 1) { for (i = 0; i < byte * wsize - keta - 1; i++) {printf(" ");} } else { for (i = 0; i < byte - keta; i++) {printf(" ");} } } #ifdef DEBUG printf("\ndmp_char(mode=%d,skip=%d)\n", *mode, *skip); #endif }