/* * bookinfo - 電子ブック/EPWING 書籍管理情報表示 * * Written by Junn Ohta (ohta@src.ricoh.co.jp). Public Domain. */ char *progname = "bookinfo"; char *version = "1.0"; char *date = "1999/01/12"; char *author = "Junn Ohta (ohta@src.ricoh.co.jp)"; #include #include #include #include #include #include #include "epw.h" #define MEGA 1048576L /* 1024 * 1024 */ #define NAME_LEN 28 /* 識別子名称表示幅 */ int verbose = FALSE; long blkno; uchr *bookfile; int main(); void usage(); int bookinfo(); long estimate(); int nonzero(); ulng val(); uchr *hexstr(); uchr *jisstr(); uchr *idname(); int idmust(); int markdel(); uchr *bktype(); uchr *protinfo(); uchr *idxhndl(); uchr *dspvalid(); uchr *dsplist(); uchr *dspstyle(); uchr *idxinfo(); int main(ac, av) int ac; char **av; { int ret; ac--, av++; while (ac > 0 && **av == '-') { switch (av[0][1]) { case 'v': case 'V': verbose = TRUE; break; case 'd': case 'D': if (markdel(&av[0][2]) == ERR) usage(); break; default: usage(); } ac--, av++; } if (ac < 1 || ac > 2) usage(); bookfile = *av; ac--, av++; blkno = 1L; if (ac == 1) blkno = strtol(*av, NULL, 0); ret = bookinfo(bookfile, blkno); if (ret == ERR) exit(1); exit(0); } void usage() { fprintf(stderr, "電子ブック/EPWING 書籍管理情報表示"); fprintf(stderr, " Ver.%s (%s)\n Written by %s, Public Domain.\n\n", version, date, author); fprintf(stderr, "使用法: %s [-v] [-d<削除IDリスト>]", progname); fprintf(stderr, " <書籍ファイル> [<情報ブロック番号>]\n\n"); fprintf(stderr, "オプション:\n"); fprintf(stderr, " -v: 複合検索管理情報を展開して表示する\n"); fprintf(stderr, " -d: 指定IDをサイズ計算でカウントしない\n"); exit(1); } int bookinfo(bookfile, blkno) char *bookfile; long blkno; { int i, j, k, must, mark; long size1, size2, cblks; uchr tmp[32], tmp2[32], tmp3[32], tmp4[32]; INFO_T *infop; ITEM_T *itemp; CINFO_T *cinfop; CENT_T *centp; CITEM_T *citemp; struct stat st; if (open_book(bookfile) == ERR) { fprintf(stderr, "%s: %s がオープンできません\n", progname, bookfile); return ERR; } if ((infop = getinfo(blkno)) == NULL) { fprintf(stderr, "%s: 書籍管理情報が取得できません\n", progname); return ERR; } close_book(); printf("; 電子ブック/EPWING 書籍管理情報"); printf(" (generated by %s v%s)\n\n", progname, version); printf("対象書籍ファイル = %s\n", bookfile); printf("情報所在ブロック = %d\n", blkno); printf("書籍構成要素数 = %d\n", infop->items); printf("予備領域1(書籍種別/保護情報) = %sH\n", hexstr(infop->resv1, tmp, RESV1_LEN)); printf(" 書籍種別: %s\n", bktype(infop->resv1)); printf(" 保護情報: %s\n", protinfo(infop->resv1)); printf("INDEX情報の取扱法 = %02XH (%s)\n", infop->idxhndl, idxhndl(infop->idxhndl)); if (nonzero(infop->resv2, RESV2_LEN)) printf("予備領域2 = %sH\n", hexstr(infop->resv2, tmp, RESV2_LEN)); printf("\n"); printf(" ID 名称 "); printf(" 先頭 サイズ INDEX情報 予備3/4\n"); itemp = infop->item; for (i = 0; i < infop->items; i++) { must = idmust(itemp->itemid); mark = must? '*': ' '; if (itemp->itemid != ID_CINFO) { /* * 複合検索以外 */ printf("%c%02X %-*s %7lu%7lu %-9s %s/%s\n", mark, itemp->itemid, NAME_LEN, idname(itemp->itemid), itemp->topblk, itemp->blks, idxinfo(itemp), hexstr(itemp->resv3, tmp, RESV3_LEN), hexstr(itemp->resv4, tmp2, RESV4_LEN)); itemp++; continue; } /* * 複合検索 */ cblks = itemp->blks; cinfop = itemp->cinfo; if (verbose) { /* * 複合検索管理情報を詳細表示 */ printf("%c%02X 複合 %-*s %7lu%7lu %-9s %s/%s\n", mark, ID_CINFO, CRESV1_LEN * 2, nonzero(cinfop->cresv1, CRESV1_LEN)? hexstr(cinfop->cresv1, tmp, CRESV1_LEN): (uchr *)"", itemp->topblk, itemp->blks, idxinfo(itemp), hexstr(itemp->resv3, tmp2, RESV3_LEN), hexstr(itemp->resv4, tmp3, RESV4_LEN)); centp = cinfop->cent; for (j = 0; j < cinfop->cents; j++) { printf(" %3s%-*s %s\n", (j < cinfop->cents - 1)? "|--": "'--", CNAME_LEN, jisstr(centp->cname, tmp, CNAME_LEN), hexstr(centp->cresv2, tmp2, CRESV2_LEN)); citemp = centp->citem; for (k = 0; k < centp->citems; k++) { printf(" %3s%c%02X %-*s %7lu%7lu %s/%s\n", (j < cinfop->cents - 1)? "| ": " ", mark, citemp->citemid, NAME_LEN, idname(citemp->citemid), citemp->ctopblk, citemp->cblks, hexstr(citemp->cresv3, tmp, CRESV3_LEN), hexstr(citemp->cresv4, tmp2, CRESV4_LEN)); cblks += citemp->cblks; citemp++; } centp++; } } else { /* * 複合検索管理情報は合計サイズだけ表示 */ centp = cinfop->cent; for (j = 0; j < cinfop->cents; j++) { citemp = centp->citem; for (k = 0; k < centp->citems; k++) { cblks += citemp->cblks; citemp++; } centp++; } printf("%c%02X %-*s ***%7lu %-9s %s/%s\n", mark, ID_CINFO, NAME_LEN, "複合検索", cblks, idxinfo(itemp), hexstr(itemp->resv3, tmp, RESV3_LEN), hexstr(itemp->resv4, tmp2, RESV4_LEN)); } itemp++; } printf("\n"); printf("表示方法の初期値情報:\n"); printf(" 有効無効フラグ = %02XH (%s)\n", infop->dspvalid, dspvalid(infop->dspvalid)); printf(" 一覧表表示 = %02XH (%s)\n", infop->dsplist, dsplist(infop->dsplist)); printf(" 本文表示法 = %02XH (%s)\n", infop->dspstyle, dspstyle(infop->dspstyle)); if (nonzero(infop->resv5, RESV5_LEN)) printf(" 予備領域5 = %sH\n", hexstr(infop->resv5, tmp, RESV5_LEN)); if (nonzero(infop->resv6, RESV6_LEN)) printf(" 予備領域6 = %sH\n", hexstr(infop->resv6, tmp, RESV6_LEN)); printf("\n"); stat(bookfile, &st); size1 = st.st_size; size2 = estimate(infop, blkno); printf("書籍ファイルサイズ = %3ldMB\n", (size1 + MEGA - 1) / MEGA); printf("マーク部分のサイズ = %3ldMB\n", (size2 + MEGA - 1) / MEGA); printf("\n"); freeinfo(infop); return OK; } /* * サイズ計算用のテーブル */ typedef struct slot_t { dword topblk; dword blks; } SLOT_T; long estimate(infop, blkno) INFO_T *infop; long blkno; { int i, j, k, m, n, num, must; long blks; ITEM_T *itemp; CINFO_T *cinfop; CENT_T *centp; CITEM_T *citemp; SLOT_T *slot; num = 1; itemp = infop->item; for (i = 0; i < infop->items; i++) { must = idmust(itemp->itemid); if (!must) { itemp++; continue; } num++; if (itemp->itemid != ID_CINFO) { itemp++; continue; } cinfop = itemp->cinfo; centp = cinfop->cent; for (j = 0; j < cinfop->cents; j++) { citemp = centp->citem; for (k = 0; k < centp->citems; k++) { num++; citemp++; } centp++; } itemp++; } slot = (SLOT_T *)malloc(sizeof(SLOT_T) * num); if (slot == NULL) return 0L; slot[0].topblk = blkno; slot[0].blks = 1L; n = 1; itemp = infop->item; for (i = 0; i < infop->items; i++) { must = idmust(itemp->itemid); if (!must) { itemp++; continue; } for (m = 0; m < n; m++) { if (slot[m].topblk == itemp->topblk) break; } if (m == n) { slot[n].topblk = itemp->topblk; slot[n].blks = itemp->blks; n++; } if (itemp->itemid != ID_CINFO) { itemp++; continue; } cinfop = itemp->cinfo; centp = cinfop->cent; for (j = 0; j < cinfop->cents; j++) { citemp = centp->citem; for (k = 0; k < centp->citems; k++) { for (m = 0; m < n; m++) { if (slot[m].topblk == citemp->ctopblk) break; } if (m == n) { slot[n].topblk = citemp->ctopblk; slot[n].blks = citemp->cblks; n++; } citemp++; } centp++; } itemp++; } blks = 0L; for (m = 0; m < n; m++) blks += slot[m].blks; free((char *)slot); return blks * BLKSIZ; } int nonzero(p, len) uchr *p; int len; { while (len--) if (*p++) return TRUE; return FALSE; } ulng val(str, len) uchr *str; int len; { ulng l; l = 0L; while (len--) l = (l << 8) + *str++; return l; } uchr * hexstr(hex, buf, len) uchr *hex, *buf; int len; { uchr *p; p = buf; while (len--) { *p++ = "0123456789ABCDEF"[*hex >> 4]; *p++ = "0123456789ABCDEF"[*hex & 0x0f]; hex++; } *p = '\0'; return buf; } uchr * jisstr(p, buf, len) uchr *p, *buf; int len; { int c1, c2; uchr *pend, *q; pend = p + len; while (pend >= p + 2 && (pend[-1] == '\0' && pend[-2] == '\0' || pend[-1] == 0x21 && pend[-2] == 0x21)) pend -= 2; q = buf; #ifdef EUC while (p < pend) *q++ = (*p++ | 0x80); #endif #ifdef SJIS while (p < pend) { c1 = *p++; c2 = *p++; if (c1 & 0x01) { c2 += 0x1f; if (c2 > 0x7e) c2++; } else { c2 += 0x7e; } c1 = (c1 + 0xe1) >> 1; if (c1 > 0x9f) c1 += 0x40; *q++ = c1; *q++ = c2; } #endif *q = '\0'; return buf; } /* * 書籍構成要素識別子表 */ typedef struct itype_t { byte idmin; byte idmax; int must; uchr *name; } ITYPE_T; ITYPE_T itypetbl[] = { { 0x00, 0x00, TRUE, "本文" }, { 0x01, 0x01, TRUE, "メニュー" }, { 0x02, 0x02, TRUE, "著作権表示" }, { 0x03, 0x03, FALSE, "条件検索見出し" }, { 0x04, 0x04, TRUE, "前方一致かな見出し" }, { 0x05, 0x05, TRUE, "前方一致表記形見出し" }, { 0x06, 0x06, TRUE, "後方一致かな見出し" }, { 0x07, 0x07, TRUE, "後方一致表記形見出し" }, { 0x08, 0x08, TRUE, "前方一致英字見出し" }, { 0x09, 0x09, TRUE, "後方一致英字見出し" }, { 0x0a, 0x0a, FALSE, "クロス検索見出し" }, { 0x0b, 0x0b, FALSE, "項目番号見出し" }, { 0x0d, 0x0d, FALSE, "項目別条件検索見出し" }, { 0x0f, 0x0f, FALSE, "図版見出し" }, { 0x20, 0x20, FALSE, "メニュー" }, { 0x21, 0x21, FALSE, "著作権表示" }, { 0x23, 0x23, FALSE, "著作権表示(1行表示用)" }, { 0x24, 0x24, FALSE, "音声見出し" }, { 0x30, 0x30, FALSE, "かなインデックス" }, { 0x40, 0x40, FALSE, "英字インデックス" }, { 0x50, 0x50, FALSE, "漢字インデックス" }, { 0x60, 0x60, FALSE, "表記形インデックス" }, { 0x70, 0x70, TRUE, "後方一致かなインデックス" }, { 0x71, 0x71, TRUE, "後方一致表記形インデックス" }, { 0x72, 0x72, TRUE, "後方一致英字インデックス" }, { 0x80, 0x80, FALSE, "条件検索インデックス" }, { 0x81, 0x81, FALSE, "クロス検索インデックス" }, { 0x90, 0x90, TRUE, "前方一致かなインデックス" }, { 0x91, 0x91, TRUE, "前方一致表記形インデックス" }, { 0x92, 0x92, TRUE, "前方一致英字インデックス" }, { 0xa0, 0xa0, FALSE, "項目番号インデックス" }, { 0xa1, 0xa1, FALSE, "項目別条件検索インデックス" }, { 0xb0, 0xb0, FALSE, "ページ検索インデックス" }, { 0xb1, 0xb1, FALSE, "漢字インデックス" }, { 0xd0, 0xd0, FALSE, "モノクロ図版" }, { 0xd1, 0xd1, FALSE, "拡張モノクロ図版" }, { 0xd2, 0xd2, FALSE, "カラー図版" }, { 0xd8, 0xd8, FALSE, "PCM音声" }, { 0xe0, 0xe0, FALSE, "色見本" }, { 0xf0, 0xf0, FALSE, "暗証" }, { 0xf1, 0xf1, TRUE, "外字(16×16ドット)" }, { 0xf2, 0xf2, TRUE, "外字(8×16ドット)" }, { 0xf3, 0xf3, TRUE, "外字(24×24ドット)" }, { 0xf4, 0xf4, TRUE, "外字(12×24ドット)" }, { 0xf5, 0xf5, TRUE, "外字(30×30ドット)" }, { 0xf6, 0xf6, TRUE, "外字(15×30ドット)" }, { 0xf7, 0xf7, TRUE, "外字(48×48ドット)" }, { 0xf8, 0xf8, TRUE, "外字(24×48ドット)" }, { 0xff, 0xff, FALSE, "複合検索管理情報" }, { 0x00, 0x2f, FALSE, "その他のテキストデータ" }, { 0x70, 0x7f, FALSE, "その他の後方一致インデックス" }, { 0x80, 0x8f, FALSE, "その他の条件検索インデックス" }, { 0x90, 0x9f, FALSE, "その他の前方一致インデックス" }, { 0xa0, 0xbf, FALSE, "その他のインデックス" }, { 0xd0, 0xdf, FALSE, "その他のマルチメディアデータ" } }; uchr * idname(id) int id; { int i, n; n = sizeof(itypetbl) / sizeof(itypetbl[0]); for (i = 0; i < n; i++) { if (id >= itypetbl[i].idmin && id <= itypetbl[i].idmax) return itypetbl[i].name; } return "???"; } int idmust(id) int id; { int i, n; n = sizeof(itypetbl) / sizeof(itypetbl[0]); for (i = 0; i < n; i++) { if (id >= itypetbl[i].idmin && id <= itypetbl[i].idmax) return itypetbl[i].must; } return FALSE; } int markdel(str) uchr *str; { int i, n; int dmin, dmax; n = sizeof(itypetbl) / sizeof(itypetbl[0]); for (i = 0; i < n; i++) itypetbl[i].must = TRUE; while (*str) { dmin = dmax = hex(str); if (dmin < 0) return ERR; str += 2; if (*str == '-') { str++; dmax = hex(str); if (dmax < 0) return ERR; str += 2; } for (i = 0; i < n; i++) { if (dmax >= itypetbl[i].idmin && dmin <= itypetbl[i].idmax) itypetbl[i].must = FALSE; } if (*str == ',') str++; } return OK; } uchr * bktype(str) uchr *str; { switch (*str & 0xf0) { case 0x00: return "国語辞典"; case 0x10: return "漢和辞典"; case 0x20: return "英和辞典"; case 0x30: return "和英辞典"; case 0x40: return "現代用語辞典"; case 0x50: return "百科事典"; case 0x60: return "一般書物"; case 0x70: return "類語辞典"; default: return "不明"; } } uchr * protinfo(str) uchr *str; { static uchr buf[160]; strcpy(buf, "表示"); strcat(buf, (str[1] & 0x01)? "禁止": "許可"); strcat(buf, ", 印刷"); strcat(buf, (str[1] & 0x02)? "禁止": "許可"); strcat(buf, ", テキスト引用"); strcat(buf, (str[1] & 0x04)? "禁止": "許可"); strcat(buf, ", 図版引用"); strcat(buf, (str[1] & 0x08)? "禁止": "許可"); strcat(buf, ",\n カラー図版引用"); strcat(buf, (str[1] & 0x10)? "許可" :"禁止"); strcat(buf, ", 動画引用"); strcat(buf, (str[1] & 0x20)? "許可" :"禁止"); strcat(buf, ", 大量引用"); strcat(buf, (str[1] & 0x80)? "許可" :"禁止"); return buf; } int hex(s) uchr *s; { int n; if (!isxdigit(s[0]) || !isxdigit(s[1])) return -1; if (s[0] >= '0' && s[0] <= '9') n = s[0] - '0'; else if (s[0] >= 'A' && s[0] <= 'F') n = s[0] - 'A' + 10; else if (s[0] >= 'a' && s[0] <= 'f') n = s[0] - 'a' + 10; n <<= 4; if (s[1] >= '0' && s[1] <= '9') n += s[1] - '0'; else if (s[1] >= 'A' && s[1] <= 'F') n += s[1] - 'A' + 10; else if (s[1] >= 'a' && s[1] <= 'f') n += s[1] - 'a' + 10; return n; } uchr * idxhndl(n) int n; { switch (n) { case 0x00: return "INDEX情報有効性に依存"; case 0x01: return "INDEX情報は無効"; case 0x02: return "INDEX情報は有効"; } return "不明"; } uchr * dspvalid(n) int n; { switch (n) { case 0x00: return "初期値情報は無効"; case 0x01: return "初期値情報は有効"; } return "不明"; } uchr * dsplist(n) int n; { switch (n) { case 0x00: return "直接本文表示"; case 0x01: return "一覧表を表示し、選択指示を受けて表示"; } return "不明"; } uchr * dspstyle(n) int n; { switch (n) { case 0x00: return "検索結果を項目単位に連続して表示"; case 0x01: return "検索結果を先頭に本文を表示"; } return "不明"; } /* * インデックス構成成分のデータ表現法 */ #define I_KATA_MASK 0x00c00000L /* カタカナ */ #define I_KATA_HIRA 0x00000000L /* ひらがなに変換して記録(k) */ #define I_KATA_ASIS 0x00400000L /* そのまま記録(.) */ #define I_LCASE_MASK 0x00300000L /* 英小文字 */ #define I_LCASE_UCASE 0x00000000L /* 英大文字に変換して記録(a) */ #define I_LCASE_ASIS 0x00100000L /* そのまま記録(.) */ #define I_SYM_MASK 0x000c0000L /* 記号 */ #define I_SYM_DEL 0x00000000L /* 記号を削除して記録(s) */ #define I_SIM_ASIS 0x00040000L /* そのまま記録(.) */ #define I_CHOU_MASK 0x00030000L /* 長音 */ #define I_CHOU_BOIN 0x00000000L /* 直前の母音に変換して記録(c)*/ #define I_CHOU_ASIS 0x00010000L /* そのまま記録(.) */ #define I_CHOU_DEL 0x00020000L /* 長音を削除して記録(C) */ #define I_SOKU_MASK 0x0000c000L /* 促音 */ #define I_SOKU_LARGE 0x00000000L /* 大きな文字に変換して記録(t)*/ #define I_SOKU_ASIS 0x00004000L /* そのまま記録(.) */ #define I_YOU_MASK 0x00003000L /* 拗音 */ #define I_YOU_LARGE 0x00000000L /* 大きな文字に変換して記録(y)*/ #define I_YOU_ASIS 0x00001000L /* そのまま記録(.) */ #define I_GAI_MASK 0x00000c00L /* 外来語用小文字 */ #define I_GAI_LARGE 0x00000000L /* 大きな文字に変換して記録(g)*/ #define I_GAI_ASIS 0x00000400L /* そのまま記録(.) */ #define I_DAKU_MASK 0x00000300L /* 濁音 */ #define I_DAKU_SEI 0x00000000L /* 清音に変換して記録(d) */ #define I_DAKU_ASIS 0x00000100L /* そのまま記録(.) */ #define I_HAN_MASK 0x000000c0L /* 半濁音 */ #define I_HAN_SEI 0x00000000L /* 清音に変換して記録(h) */ #define I_HAN_ASIS 0x00000040L /* そのまま記録(.) */ #define I_RESV_MASK 0x0000003fL /* 予備領域 */ uchr * idxinfo(item) ITEM_T *item; { dword d; static uchr buf[10]; if (item->idxvalid == 0x01) return ""; d = item->idxinfo; buf[0] = ((d & I_KATA_MASK ) == I_KATA_HIRA )? 'k': '.'; buf[1] = ((d & I_LCASE_MASK) == I_LCASE_UCASE)? 'a': '.'; buf[2] = ((d & I_SYM_MASK ) == I_SYM_DEL )? 's': '.'; buf[3] = ((d & I_CHOU_MASK ) == I_CHOU_BOIN )? 'c': ((d & I_CHOU_MASK ) == I_CHOU_DEL )? 'C': '.'; buf[4] = ((d & I_SOKU_MASK ) == I_SOKU_LARGE )? 't': '.'; buf[5] = ((d & I_YOU_MASK ) == I_YOU_LARGE )? 'y': '.'; buf[6] = ((d & I_GAI_MASK ) == I_GAI_LARGE )? 'g': '.'; buf[7] = ((d & I_DAKU_MASK ) == I_DAKU_SEI )? 'd': '.'; buf[8] = ((d & I_HAN_MASK ) == I_HAN_SEI )? 'h': '.'; buf[9] = '\0'; return buf; }