/* * od.c -- オクタルダンプ。ただし16進でしか表示しないよん。 * * Copyright (C) 1990 * Toshihiro Kanda. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Toshihiro Kanda. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY TOSHIHIRO KANDA AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL TOSHIHIRO KANDA OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ static char rcsid[] = "$Id: xd.c,v 2.3 1992/11/13 02:33:10 candy Exp candy $"; /* * $Log: xd.c,v $ * Revision 2.3 1992/11/13 02:33:10 candy * support byte order : motorola, intel, vax * * Revision 2.2 1992/07/30 06:10:40 candy * 8進出力追加 * その他大幅な改造 * _fmtout.s が "%0*x" を処理できないバグを取った * うーん、マンダム(古い!) * * Revision 2.1 1992/06/10 01:20:12 candy * gmalloc バグフィクス記念 * * Revision 1.3 1992/06/10 01:13:46 candy * CD-ROM 発売記念 * * Revision 1.2 90/11/17 11:18:28 CANDY * 漢字表示関係の修正 * * Revision 1.1 90/11/17 11:12:35 CANDY * Initial revision * */ #include #include #include #include #include #include #ifdef __HUMAN68K__ #include #endif #ifdef unix #include #endif #include #define FALSE 0 #define TRUE 1 #define SUCCESS 0 #define ERROR (-1) char *myname; char usage_msg[] = "Octal Dump V0.8087 Copyright (C) 1990,1992,1994 by candy\n" "Usage: %s\n" "\t-b[n]\t1ワードのバイト数\n" "\t-l\t1ワード4バイト(==-b4)\n" "\t-w[n]\t1列のバイト数\n" "\t-2\t2進ダンプ\n" "\t-o\t8進ダンプ\n" "\t-d\t10進ダンプ\n" "\t-x\t16進ダンプ\n" "\t-v\t纏めない\n" "\t-Sn\t開始\n" "\t-Ln\tサイズ\n" "\t-C\t文字表示しない\n" "\t-c\t漢字表示しない\n" "\t-A\tアドレス表示しない\n" "\t-N\t数値表示しない\n" "\t-Ox\tバイトオーダ: OM=motorola, OI=intel, OD=PDP\n" #ifdef __HUMAN68K__ "\t-B\tバイナリ\n" "\t-T\tバイナリ\n" #endif /* __HUMAN68K__ */ ; #define MAXROW 512 int show_char = TRUE; /* -C */ int show_kanji = TRUE; /* -c */ int show_num = TRUE; /* -N */ int show_addr = TRUE; /* -A */ int uniq = TRUE; /* ~-v */ int echo; /* -e */ int row = 16; /* -w[n] */ int word = 1; /* -b[n] -l */ enum output_base_t { IN_BINARY, IN_OCTAL, IN_DECIMAL, IN_HEXA }; enum output_base_t output_base = IN_HEXA; /* -2 -o -d -x */ #ifdef __HUMAN68K__ enum openmode_t { OPEN_TEXT, OPEN_BINARY }; enum openmode_t openmode = OPEN_BINARY; /* -B */ #endif enum byte_order_t { MOTOROLA, INTEL, PDP }; /* * sprintf(dst, "%0*lb") emulation */ int sprintb(char *dst, const char *fmt, ...) { int width; unsigned long data; #define LONG_BIT (CHAR_BIT * sizeof(long)) const unsigned long msb = 1U << (LONG_BIT - 1); int i, minwidth = 0; char buf[LONG_BIT + 2], *d = buf; { va_list ap; va_start(ap, fmt); width = va_arg(ap, int); data = va_arg(ap, unsigned long); va_end(ap); } for (i = 0; i < LONG_BIT; i++) { if (data & msb) { *d++ = '1'; if (minwidth == 0) minwidth = LONG_BIT - i; } else { *d++ = '0'; } data <<= 1; }/* for */ *d = '\0'; if (minwidth == 0) minwidth = 1; if (width < minwidth) width = minwidth; strcpy(dst, d - width); return width; }/* sprintb */ /* * */ int ndump(char *dst, const void *src_, int len, int word, const char *form, int wid_tbl[4], enum byte_order_t bo) { const char *src = src_; char *orgdst = dst; int bytecount = 0, wid = wid_tbl[word - 1]; int (*sprint)(char *, const char *, ...) = strcmp(form, "%0*lb") == 0 ? sprintb : sprintf; if (word > 4) word = 4; switch (bo) { case MOTOROLA: { unsigned long x = 0; while (len-- > 0) { x = (x << CHAR_BIT) + (unsigned char)*src++; if (++bytecount == word) { dst += sprint(dst, form, wid, x); *dst++ = ' '; bytecount = 0; x = 0; } }/* while */ if (bytecount != 0) { dst += sprint(dst, form, wid_tbl[bytecount - 1], x); } } break; case INTEL: { char xbuf[4]; memset(xbuf, 0, 4); while (len-- > 0) { xbuf[bytecount] = (unsigned char)*src++; if (++bytecount == word) { unsigned long x = *(unsigned long *)xbuf; dst += sprint(dst, form, wid, x); *dst++ = ' '; bytecount = 0; memset(xbuf, 0, 4); } }/* while */ if (bytecount != 0) { unsigned long x = *(unsigned long *)xbuf; dst += sprint(dst, form, wid_tbl[bytecount - 1], x); } } break; case PDP: { char xbuf[4]; memset(xbuf, 0, 4); while (len-- > 0) { xbuf[bytecount] = (unsigned char)*src++; if (++bytecount == word) { unsigned long x = word <= 2 ? *(unsigned short *)xbuf : *(unsigned long *)xbuf; dst += sprint(dst, form, wid, x); *dst++ = ' '; bytecount = 0; memset(xbuf, 0, 4); } }/* while */ if (bytecount != 0) { unsigned long x = *(unsigned long *)xbuf; dst += sprint(dst, form, wid_tbl[bytecount - 1], x); } } break; }/* switch */ if (dst > orgdst && dst[-1] == ' ') dst--; *dst = '\0'; return dst - orgdst; }/* ndump */ /* * */ #ifndef is1kanji /* [ */ #ifdef EUC #define is1kanji(c) ((0x81<=(unsigned char)(c))&&((unsigned char)(c)<=0xfe)) #else #define is1kanji(c) (((0x81<=(unsigned char)(c))&&((unsigned char)(c)<=0x9f))||((0xe0<=(unsigned char)(c))&&((unsigned char)(c)<=0xfc))) #endif #endif /* ] */ int cdump(char *dst, const char *src, int len, int kanjiok) { char *orgdst = dst; while (len-- > 0) { int ch; ch = (unsigned char)*src++; if (ch != '\0' && isascii(ch) && isprint(ch)) { *dst++ = ch; } else if (kanjiok && is1kanji(ch)) { if (len > 0) { len--; ch = (unsigned char)*src++; } else ch = 0; if (iscntrl(ch) || ch >= 0xff) ch = '.'; *dst++ = ch; } else { *dst++ = '.'; } }/* while */ *dst = '\0'; return dst - orgdst; }/* cdump */ /* base_width[base][byte] = 8 * byte / log2(base) */ int base_width[][4] = { /* 1 2 3 4 */ { 8, 16, 24, 32 }, /* bin */ { 3, 6, 8, 11 }, /* oct */ { 3, 5, 8, 10 }, /* dec */ { 2, 4, 6, 8 }, /* hex */ }; char *addr_forms[] = { "%08lx", "%08lx", "%08lx", "%08lx", }; char *num_forms[] = { "%0*lb", "%0*lo", "%*ld", "%0*x", }; enum byte_order_t byte_order; /* * */ int fod(FILE *fp, long start, long size) { int red, last_red = 0, grouping = FALSE; long address = start; char lbuf1[MAXROW], lbuf2[MAXROW], outline[1024]; const char *addr_form = addr_forms[output_base]; const char *num_form = num_forms[output_base]; char *lbuf = lbuf1, *last = lbuf2; fseek(fp, start, SEEK_SET); while (size > 0 && (red = fread(lbuf, sizeof(char), row, fp)) != 0) { size -= row; /* red ? */ if (uniq && red == last_red && memcmp(lbuf, last, red) == 0) { if (!grouping) { puts("*"); grouping = TRUE; } } else { char *dst = outline; if (show_addr) { dst += sprintf(dst, addr_form, address); } if (show_num) { if (dst != outline) *dst++ = ' '; dst += ndump(dst, lbuf, red, word, num_form, base_width[output_base], byte_order); } if (show_char) { if (dst != outline) { *dst++ = ' '; *dst++ = ' '; } dst += cdump(dst, lbuf, red, show_kanji); } { char *p = last; last = lbuf; lbuf = p; last_red = red; grouping = FALSE; } *dst = '\0'; puts(outline); } address += red; }/* while */ return 0; }/* fod */ /* * */ int od(char *name, long start, long size) { int err; FILE *fp; const char *md = "r"; #ifdef __HUMAN68K__ if (openmode == OPEN_BINARY) md = "rb"; #endif err = ERROR; if (name[0] == '-' && name[1] == '\0') fp = stdin; else fp = fopen(name, md); if (fp == NULL) { fprintf(stderr, "%s: cannot open %s\n", myname, name); } else { if (echo) printf("%s\n", name); err = fod(fp, start, size); if (fp != stdin) fclose(fp); } return err; }/* nain */ /* * */ #define ISFILE(str) (*(str) != '-' || *((str) + 1) == '\0') void main(int argc, char *argv[]) { int i, nf = 0, show_usage = FALSE, result; long start = 0, size = LONG_MAX; myname = argv[0]; result = 0; { unsigned long test = 0x12345678; /* MOTOROLA 0x12 0x34 0x56 0x78 */ /* INTEL 0x78 0x56 0x34 0x12 */ /* PDP 0x34 0x12 0x78 0x56 */ unsigned char *c = (unsigned char *)&test; switch (*c) { default: case 0x12: byte_order = MOTOROLA; break; case 0x78: byte_order = INTEL; break; case 0x34: byte_order = PDP; break; }/* switch */ } for (i = 1; i < argc; i++) { char *par; par = argv[i]; if (!ISFILE(par)) { int followed = TRUE; par++; while (*par != '\0' && followed) { switch (*par++) { default: case '?': case 'V': show_usage = TRUE; followed = FALSE; break; case '2': output_base = IN_BINARY; break; case 'o': output_base = IN_OCTAL; break; case 'i': case 'd': output_base = IN_DECIMAL; break; case 'x': output_base = IN_HEXA; break; case 'b': word = 1; if (isdigit((unsigned char)*par)) { word = (unsigned char)*par++ - '0'; if (word <= 0 || word > 4) word = 2; } break; case 'l': word = 4; break; case 'v': uniq = FALSE; break; case 'e': echo = TRUE; break; case 'w': case 'S': case 'L': followed = FALSE; { int opt = par[-1]; if (*par == '\0') { if (i + 1 < argc) { par = argv[++i]; argv[i] = "-f"; } else show_usage = TRUE; } if (!show_usage) { switch (opt) { case 'w': row = strtol(par, NULL, 0); if (row <= 0 || row > MAXROW) row = 32; break; case 'S': start = strtol(par, NULL, 0); break; case 'L': size = strtol(par, NULL, 0); break; }; } } break; case 'c': show_kanji = FALSE; break; case 'A': show_addr = FALSE; break; case 'C': show_char = FALSE; break; case 'N': show_num = FALSE; break; #ifdef __HUMAN68K__ case 'B': openmode = OPEN_BINARY; break; case 'T': openmode = OPEN_TEXT; break; #endif /* __HUMAN68K__ */ case 'O': byte_order = (*par == 'P' ? PDP : *par == 'I' ? INTEL : MOTOROLA); par++; break; }/* switch */ }/* while */ } else {/* filename */ nf++; } }/* for */ if (show_usage) { fprintf(stderr, usage_msg, myname); exit(1); } result = 0; if (nf == 0) { #ifdef __HUMAN68K__ if (openmode == OPEN_BINARY && !isatty(0)) { setmode(0, 0x400); /* STDIN, O_BINARY */ #ifdef HUMAN68K fmode(stdin, TRUE); /* set binary mode */ #endif } #endif fod(stdin, start, size); } else { for (i = 1; i < argc; i++) { char *par; par = argv[i]; if (ISFILE(par)) { od(par, start, size); } }/* for */ } exit(result); }/* main */