epwutil-1.1.orig/0042755000175000017500000000000007075276600013340 5ustar mhattamhattaepwutil-1.1.orig/README0100644000175000017500000000150506646727130014216 0ustar mhattamhatta■電子ブック/EPWING活用ユーティリティー EPWUTIL EPWUTILは、電子ブックやEPWING規格のCD-ROM辞書をハードディスクに置いて使う際 に、辞書の有効利用を図るためにCD-ROM辞書の構成ファイルを一部改変するMS-DOS/ UNIX用のユーティリティーの集まりです。 ・CD-ROMカタログを編集し、不要な書籍を削除したり、同一規格の複数のCD-ROMカタ ログを統合したりすることができます。(catdump) ・書籍ファイルから図版・音声などのマルチメディアデータや条件検索・複合検索の インデックスを削除し、辞書を小さくできます。(squeeze) ・書籍ファイルの構成情報を調べ、辞書を軽量化するための指針を得ることができま す。(bookinfo) bookinfoとsqueezeは、EPWING V4以降の圧縮書籍を含むいくつかの書籍には対応して いません。具体的な内容についてはepwutil.docの「5.制約事項」をご覧ください。 太田純 (Junn Ohta) Internet: ohta@src.ricoh.co.jp (メールはこちらまで) NIFTY: JCF00656 epwutil-1.1.orig/bookinfo.c0100644000175000017500000004233006646727126015316 0ustar mhattamhatta/* * 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; } epwutil-1.1.orig/bookinfo.man0100644000175000017500000002227306646727127015654 0ustar mhattamhatta名称 bookinfo - 電子ブック/EPWINGの書籍管理情報を表示する バージョン 1.0 - 1999/01/12 形式 bookinfo [-v] [-d<削除IDリスト>] <書籍ファイル> [<情報ブロック番号>] オプション -v 複合検索管理情報を展開して表示する -d<削除IDリスト> <削除IDリスト>に並べた書籍要素のサイズをサイズ合計の計算でカ ウントしない <書籍ファイル> 電子ブック/EPWINGの書籍ファイル(電子ブックのstart、EPWINGの honmon) <情報ブロック番号> 書籍ファイル中で書籍管理情報のあるブロック番号(catdumpの出力 でInfoBlockとして表示された数値、省略時の値は1) 使用例 Dドライブの電子ブック版広辞苑本体の書籍管理情報を表示する(MS-DOS) C> bookinfo d:\koujien\start DドライブのEPWING広辞苑本体の書籍管理情報を表示する(MS-DOS) C> bookinfo d:\koujien\data\honmon 上記の例で図版・音声などのマルチメディアデータのみを削除した場合の サイズを表示する C> bookinfo -dd0-fe d:\koujien\data\honmon 説明 電子ブックやEPWINGの検索対象となる書籍ファイル(ファイル名は電子ブッ クではstart、EPWINGではhonmonなど)には、本文やメニュー、著作権表示、 インデックス情報、図版、音声など、さまざまな構成要素が含まれている。 bookinfoは書籍ファイルにどんな構成要素があるか、それぞれはどのブロッ ク位置から始まってどれだけのサイズがあるかなどの情報を表示する。 bookinfoを使うと、書籍ファイルからインデックスやマルチメディアデータ の構成要素を削除したときに削減可能なサイズの指針が得られる。bookinfo はEBXAのロゴのある電子ブック(1994年以降のもの)とEPWINGの非圧縮書籍に 対応している。 bookinfoでEPWING版広辞苑第四版本体の書籍ファイル管理情報を表示した結 果を以下に示す。 C> bookinfo d:\koujien\data\honmon ; 電子ブック/EPWING 書籍管理情報 (generated by bookinfo v1.0) 対象書籍ファイル = d:\koujien\data\honmon 情報所在ブロック = 1 書籍構成要素数 = 25 予備領域1(書籍種別/保護情報) = 0000H 書籍種別: 国語辞典 保護情報: 表示許可, 印刷許可, テキスト引用許可, 図版引用許可, カラー図版引用禁止, 動画引用禁止, 大量引用禁止 INDEX情報の取扱法 = 04H (不明) ID 名称 先頭 サイズ INDEX情報 予備3/4 *00 本文 2 17737 kasctygdh 00/0000 30 かなインデックス 17739 3225 kasctygdh 00/0000 60 表記形インデックス 20964 3504 kasc..... 00/0000 *90 前方一致かなインデックス 24468 3976 kasctygdh 00/0000 *04 前方一致かな見出し 28444 3576 kasctygdh 00/0000 *91 前方一致表記形インデックス 32020 5014 kasc..... 00/0000 *05 前方一致表記形見出し 37034 7327 kasctygdh 00/0000 *70 後方一致かなインデックス 44361 3976 kasctygdh 00/0000 *06 後方一致かな見出し 48337 3576 kasctygdh 00/0000 *71 後方一致表記形インデックス 51913 5014 kasc..... 00/0000 *07 後方一致表記形見出し 56927 7327 kasctygdh 00/0000 80 条件検索インデックス 64254 15073 kasc..... 00/0000 03 条件検索見出し 79327 50546 kasctygdh 00/0000 81 クロス検索インデックス 129873 217 kasc..... 00/0000 0A クロス検索見出し 130090 409 kasctygdh 00/0000 *01 メニュー 130499 150 kasctygdh 00/0000 FF 複合検索 *** 19173 kasctygdh 00/0000 FF 複合検索 *** 7493 kasctygdh 00/0000 FF 複合検索 *** 6311 kasctygdh 00/0000 FF 複合検索 *** 4308 kasctygdh 00/0000 D0 モノクロ図版 167934 13242 kasctygdh 00/0000 D2 カラー図版 181176 35471 kasctygdh 00/0000 *02 著作権表示 216647 1 kasctygdh 00/0000 E0 色見本 216648 266 kasctygdh 00/0000 D8 PCM音声 216914 4887 kasctygdh 00/0000 表示方法の初期値情報: 有効無効フラグ = 01H (初期値情報は有効) 一覧表表示 = 01H (一覧表を表示し、選択指示を受けて表示) 本文表示法 = 01H (検索結果を先頭に本文を表示) 書籍ファイルサイズ = 434MB マーク部分のサイズ = 113MB 重要な情報としては、予備領域1にある書籍種別と保護情報、中間に並べら れた書籍構成要素一覧、そして最後にある書籍ファイルとマーク部分のサイ ズがある。INDEX情報の取扱法、表示方法の初期値情報、また予備領域1以外 の予備と書かれた部分については、ソースコードとJIS X4081規格票を参照 していただきたい。 予備領域1には書籍種別と保護情報がある。保護情報は出版社がこの辞書コ ンテンツに与えた利用許可の詳細を示している。このデータを書き換えては ならないし、この範囲を超えて辞書データを利用することは好ましくない。 中間の書籍構成要素一覧には、構成要素のIDと種別名称、書籍ファイル中の 開始ブロック位置と占有ブロック数、その他の情報が含まれる。1ブロック は2048バイトであり、ブロック位置は1から始まる。通常は書籍管理情報が ブロック1にあるため、一覧中の最も若い要素はブロック2から開始されるこ とになる。 構成要素には以下の種別がある。IDは電子ブックとEPWINGで共通だが、いず れか一方でしか使われない構成要素もある。たとえば外字はEPWINGでは別フ ァイルであり、ここには現れない。 ============================== ID 名称 ------------------------------ 00 本文 01 メニュー 02 著作権表示 03 条件検索見出し 04 前方一致かな見出し 05 前方一致表記形見出し 06 後方一致かな見出し 07 後方一致表記形見出し 08 前方一致英字見出し 09 後方一致英字見出し 0A クロス検索見出し 0B 項目番号見出し 0D 項目別条件検索見出し 0F 図版見出し 20 メニュー 21 著作権表示 23 著作権表示(1行表示用) 24 音声見出し 30 かなインデックス 40 英字インデックス 50 漢字インデックス 60 表記形インデックス 70 後方一致かなインデックス 71 後方一致表記形インデックス 72 後方一致英字インデックス 80 条件検索インデックス 81 クロス検索インデックス 90 前方一致かなインデックス 91 前方一致表記形インデックス 92 前方一致英字インデックス A0 項目番号インデックス A1 項目別条件検索インデックス B0 ページ検索インデックス B1 漢字インデックス D0 モノクロ図版 D1 拡張モノクロ図版 D2 カラー図版 D8 PCM音声 E0 色見本 F0 暗証 F1 外字(16×16ドット) F2 外字(8×16ドット) F3 外字(24×24ドット) F4 外字(12×24ドット) F5 外字(30×30ドット) F6 外字(15×30ドット) F7 外字(48×48ドット) F8 外字(24×48ドット) FF 複合検索管理情報 ============================== IDが00〜02の構成要素は基本的なデータであり、これらが存在しない書籍は 検索ソフトによっては正しく扱えないかもしれない。03〜0Fはインデックス 検索の結果一覧を表示する際の見出しデータであり、対応するインデックス と対にして使われる。20〜60の構成要素はおそらく古い電子ブックのための 構成要素であり、最近の検索ソフトでは参照されないらしい。70〜BFは各種 インデックス検索のためのインデックスだ。D0〜EFは各種マルチメディアデ ータであり、F1〜F8は電子ブックの外字データだ。FFは複合検索のための管 理情報ブロックを意味している。 複合検索はさらに下位の構成要素からなるため、それら下位の構成要素の占 有ブロック数の合計だけが示される。下位の構成要素は共有されることがあ り、その合計サイズは必ずしも全体の合計サイズに寄与しない。bookinfoに -vオプションを指定すると、複合検索の下位構成要素も展開して表示される。 以下は最初の複合検索に対応する「bookinfo -v」での表示内容だ。 FF 複合 130649 1 kasctygdh 00/0000 |--地域(→参照) 00 | A1 項目別条件検索インデックス 130650 54 00/01.. | 0D 項目別条件検索見出し 130704 160 00/01.. | 01 メニュー 130864 1 00/01.. |--時代(→参照) 00 | A1 項目別条件検索インデックス 130865 56 00/01.. | 0D 項目別条件検索見出し 130921 164 00/01.. | 01 メニュー 131085 1 00/01.. |--キーワード 00 | 91 前方一致表記形インデックス 131086 3138 00/01.. | 05 前方一致表記形見出し 134224 6230 00/01.. '--キーワード 00 91 前方一致表記形インデックス 140454 3138 00/01.. 05 前方一致表記形見出し 143592 6230 00/01.. 末尾にあるマーク部分のサイズは、IDが「*」でマークされた構成要素と書 籍管理情報ブロックを合計したサイズをMB(1024KB)単位で示している。標準 では以下の構成要素、つまり前方一致/後方一致検索とメニュー検索で辞書 を利用するために必要な構成要素だけがマークされる。 00, 01, 02 (本文テキスト、メニュー) 04, 05, 06, 07, 08, 09 (前方/後方一致見出し) 70, 71, 72, 90, 91, 92 (前方/後方一致インデックス) F1, F2, F3, F4, F5, F6, F7, F8 (電子ブック外字) EPWING版広辞苑の例では書籍ファイルサイズが434MB、マーク部分のサイズ が113MBであり、条件検索、クロス検索、複合検索、マルチメディアデータ などの構成要素を削除すれば、書籍ファイルのサイズを1/4程度に削減でき ることがわかる。 マークの対象は-dオプションで変更できる。-dの後には空白をあけずにマー クしない構成要素のIDをカンマで区切って並べる。「-」を使ってIDの範囲 を指定することもできる。省略時の動作は次の-dオプションと等しい。 -d03,0a-6f,73-8f,93-ef,f9-ff なお、-dオプションの指定方法はsqueezeと共通であり、ある-dオプション を指定したときのsqueezeの出力結果のサイズは、同じ-dオプションを指定 してbookinfoを実行することによって予測できる。 epwutil-1.1.orig/bread.c0100644000175000017500000001124006646727127014562 0ustar mhattamhatta/* * bread.c - 電子ブック/EPWINGユーティリティー 書籍読み込みモジュール * * Written by Junn Ohta (ohta@src.ricoh.co.jp). Public Domain. */ #include #include #include #ifdef MSDOS #include #endif #ifdef UNIX #include #endif #include "epw.h" #ifndef O_BINARY #define O_BINARY 0 #endif static int rfd = -1; static long rblkno; static byte rblkbuf[BLKSIZ]; static byte *rp, *rendp = &rblkbuf[BLKSIZ]; int open_book(file) uchr *file; { if (rfd != -1) close_book(); if ((rfd = open(file, O_RDONLY|O_BINARY)) < 0) return ERR; rblkno = 0L; if (read_block() == ERR) return ERR; return OK; } int close_book() { if (rfd == -1) return ERR; if (close(rfd) < 0) return ERR; return OK; } int locate_block(blk) long blk; { if (rfd == -1) return ERR; if (blk <= 0L) return ERR; if (rblkno == blk) { rp = rblkbuf; return OK; } if (lseek(rfd, (blk - 1L) * BLKSIZ, 0) < 0) return ERR; if (read_block() == ERR) return ERR; rblkno = blk; return OK; } int read_block() { if (rfd == -1) return ERR; if (read(rfd, (char *)rblkbuf, BLKSIZ) < BLKSIZ) return ERR; rp = rblkbuf; rblkno++; return OK; } long cur_block() { return rblkno; } int cur_off() { return rp - rblkbuf; } byte getbyte() { if (rp >= rendp) read_block(); return *rp++; } word getword() { word w; w = getbyte() << 8; w += getbyte(); return w; } dword getdword() { dword d; d = (dword)getbyte() << 24; d += (dword)getbyte() << 16; d += (dword)getbyte() << 8; d += (dword)getbyte(); return d; } long getbcd(len) int len; { int err; byte b1, b2; long d; err = FALSE; d = 0L; while (len--) { b2 = getbyte(); b1 = b2 >> 4; b2 &= 0x0f; if (b1 > 9 || b2 > 9) err = TRUE; d = d * 100 + b1 * 10 + b2; } if (err) return -1L; return d; } byte * getbytes(buf, len) byte *buf; int len; { byte *p; p = buf; while (len--) *p++ = getbyte(); return buf; } INFO_T * getinfo(blk) long blk; { int i, j, k; INFO_T *infop; ITEM_T *itemp; CINFO_T *cinfop; CENT_T *centp; CITEM_T *citemp; if (locate_block(blk) == ERR) return NULL; infop = (INFO_T *)malloc(sizeof(INFO_T)); if (infop == NULL) return NULL; infop->items = getword(); getbytes(infop->resv1, RESV1_LEN); infop->idxhndl = getbyte(); getbytes(infop->resv2, RESV2_LEN); infop->item = (ITEM_T *)malloc(sizeof(ITEM_T) * infop->items); if (infop->item == NULL) return NULL; itemp = infop->item; for (i = 0; i < infop->items; i++) { itemp->itemid = getbyte(); getbytes(itemp->resv3, RESV3_LEN); itemp->topblk = getdword(); itemp->blks = getdword(); itemp->idxvalid = getbyte(); itemp->idxinfo = getbyte() << 16; itemp->idxinfo += getbyte() << 8; itemp->idxinfo += getbyte(); getbytes(itemp->resv4, RESV4_LEN); itemp->cinfo = NULL; itemp++; } infop->dspvalid = getbyte(); getbytes(infop->resv5, RESV5_LEN); infop->dsplist = getbyte(); infop->dspstyle = getbyte(); getbytes(infop->resv6, RESV6_LEN); itemp = infop->item; for (i = 0; i < infop->items; i++) { if (itemp->itemid != ID_CINFO) { itemp++; continue; } if (locate_block(itemp->topblk) == ERR) return NULL; itemp->cinfo = (CINFO_T *)malloc(sizeof(CINFO_T)); if (itemp->cinfo == NULL) return NULL; cinfop = itemp->cinfo; cinfop->cents = getword(); getbytes(cinfop->cresv1, CRESV1_LEN); cinfop->cent = (CENT_T *)malloc(sizeof(CENT_T) * cinfop->cents); if (cinfop->cent == NULL) return NULL; centp = cinfop->cent; for (j = 0; j < cinfop->cents; j++) { centp->citems = getbyte(); getbytes(centp->cresv2, CRESV2_LEN); getbytes(centp->cname, CNAME_LEN); centp->citem = (CITEM_T *)malloc(sizeof(CITEM_T) * centp->citems); if (centp->citem == NULL) return NULL; citemp = centp->citem; for (k = 0; k < centp->citems; k++) { citemp->citemid = getbyte(); getbytes(citemp->cresv3, CRESV3_LEN); citemp->ctopblk = getdword(); citemp->cblks = getdword(); getbytes(citemp->cresv4, CRESV4_LEN); citemp++; } centp++; } itemp++; } return infop; } void freeinfo(infop) INFO_T *infop; { int i, j; ITEM_T *itemp; CINFO_T *cinfop; CENT_T *centp; itemp = infop->item; for (i = 0; i < infop->items; i++) { if (itemp->cinfo != NULL) { cinfop = itemp->cinfo; centp = cinfop->cent; for (j = 0; j < cinfop->cents; j++) { free((char *)centp->citem); centp++; } free((char *)cinfop->cent); free((char *)itemp->cinfo); } itemp++; } free((char *)infop->item); free((char *)infop); } epwutil-1.1.orig/bwrite.c0100644000175000017500000000766506646727127015021 0ustar mhattamhatta/* * bread.c - 電子ブック/EPWINGユーティリティー 書籍書き出しモジュール * * Written by Junn Ohta (ohta@src.ricoh.co.jp). Public Domain. */ #include #include #include #include #ifdef MSDOS #include #endif #ifdef UNIX #include #endif #include "epw.h" #ifndef O_BINARY #define O_BINARY 0 #endif static int wfd = -1; static int werr = 0; static long wblkno; static byte wblkbuf[BLKSIZ]; static byte *wp, *wendp = &wblkbuf[BLKSIZ]; int open_newbook(file) uchr *file; { if (wfd != -1) close_book(); if ((wfd = open(file, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0644)) < 0) return ERR; memset(wblkbuf, '\0', BLKSIZ); wp = wblkbuf; wblkno = 1L; werr = 0; return OK; } int close_newbook() { if (wfd == -1) return ERR; if (wp > wblkbuf) write_newblock(); if (close(wfd) < 0) return ERR; return OK; } int locate_newblock(blk) long blk; { if (wfd == -1) return ERR; if (blk <= 0L) return ERR; if (wp > wblkbuf) write_newblock(); if (lseek(wfd, (blk - 1L) * BLKSIZ, 0) < 0) return ERR; wp = wblkbuf; wblkno = blk; return OK; } int write_newblock() { if (wfd == -1) return ERR; if (write(wfd, (char *)wblkbuf, BLKSIZ) < BLKSIZ) return ERR; memset(wblkbuf, '\0', BLKSIZ); wp = wblkbuf; wblkno++; return OK; } long cur_newblock() { return wblkno; } int cur_newoff() { return wp - wblkbuf; } int get_error() { return werr; } void reset_error() { werr = 0; } int putbyte(b) byte b; { if (wp >= wendp) { if (write_newblock() == ERR) werr++; } *wp++ = b; return OK; } int putword(w) word w; { putbyte(w >> 8); putbyte(w & 0xff); return OK; } int putdword(d) dword d; { putbyte(d >> 24); putbyte((d >> 16) & 0xff); putbyte((d >> 8) & 0xff); putbyte(d & 0xff); return OK; } int putbcd(d, len) dword d; int len; { int i; dword n; byte *p, buf[10]; p = buf; while (len--) { *p = (int)(d % 10L); d /= 10; *p |= (int)(d % 10L) << 4; d /= 10; p++; } while (p > buf) { putbyte(p[-1]); p--; } return OK; } int putbytes(buf, len) byte *buf; int len; { byte *p; p = buf; while (len--) putbyte(*p++); return OK; } int putinfo(infop, blk) INFO_T *infop; long blk; { int i, j, k; ITEM_T *itemp; CINFO_T *cinfop; CENT_T *centp; CITEM_T *citemp; if (locate_newblock(blk) == ERR) return ERR; putword(infop->items); putbytes(infop->resv1, RESV1_LEN); putbyte(infop->idxhndl); putbytes(infop->resv2, RESV2_LEN); itemp = infop->item; for (i = 0; i < infop->items; i++) { putbyte(itemp->itemid); putbytes(itemp->resv3, RESV3_LEN); putdword(itemp->topblk); putdword(itemp->blks); putbyte(itemp->idxvalid); putbyte((itemp->idxinfo >> 16) & 0xff); putbyte((itemp->idxinfo >> 8) & 0xff); putbyte(itemp->idxinfo & 0xff); putbytes(itemp->resv4, RESV4_LEN); itemp++; } putbyte(infop->dspvalid); putbytes(infop->resv5, RESV5_LEN); putbyte(infop->dsplist); putbyte(infop->dspstyle); putbytes(infop->resv6, RESV6_LEN); if (write_newblock() == ERR) return ERR; itemp = infop->item; for (i = 0; i < infop->items; i++) { if (itemp->itemid != ID_CINFO) { itemp++; continue; } if (locate_newblock(itemp->topblk) == ERR) return ERR; cinfop = itemp->cinfo; putword(cinfop->cents); putbytes(cinfop->cresv1, CRESV1_LEN); centp = cinfop->cent; for (j = 0; j < cinfop->cents; j++) { putbyte(centp->citems); putbytes(centp->cresv2, CRESV2_LEN); putbytes(centp->cname, CNAME_LEN); citemp = centp->citem; for (k = 0; k < centp->citems; k++) { putbyte(citemp->citemid); putbytes(citemp->cresv3, CRESV3_LEN); putdword(citemp->ctopblk); putdword(citemp->cblks); putbytes(citemp->cresv4, CRESV4_LEN); citemp++; } centp++; } if (write_newblock() == ERR) return ERR; itemp++; } return OK; } epwutil-1.1.orig/catdump.c0100644000175000017500000006110707075275511015141 0ustar mhattamhatta/* * catdump - 電子ブック/EPWING カタログ/テキスト変換 * * Written by Junn Ohta (ohta@src.ricoh.co.jp). Public Domain. * Modified by yamagata@nwgpc.kek.jp on 2000/04/13 */ char *progname = "catdump"; char *version = "1.1"; char *date = "1999/01/13"; char *author = "Junn Ohta (ohta@src.ricoh.co.jp)"; #include #include #include #include #include #include #include typedef unsigned char uchr; #ifndef O_BINARY #define O_BINARY 0 #endif #define OK 0 #define ERR (-1) #define FALSE 0 #define TRUE 1 /* * 処理内容 */ #define DUMP 0 /* カタログ → テキスト */ #define UNDUMP 1 /* テキスト → カタログ */ /* * 書籍種別 */ #define EB 0 /* 電子ブック */ #define EPWING 1 /* EPWING1 = 1, EPWING2 = 2, ... */ #define EPWING2 2 /* EPWING2 */ #define EPWING4 4 /* EPWING4 */ /* * 書籍ブロックサイズ(= カタログファイルサイズ) */ #define BLKSIZ 2048 /* * カタログファイルの構造 * (登録書籍数はEBで最大50、EPWINGで最大12) */ #define C_BOOKSLEN 2 /* 登録書籍数 */ #define C_CDTYPELEN 2 /* 書籍種別 */ #define C_SELECTLEN 2 /* 書籍選択画面の有無、書籍番号 */ #define C_RSVLEN 10 /* 将来拡張用 */ /* (以下登録書籍数だけくり返し) */ #define B_BKTYPELEN 2 /* 書籍情報 */ #define B_TTLLEN_EB 30 /* 書籍名称(電子ブック) */ #define B_TTLLEN_EPW 80 /* 書籍名称(EPWING) */ #define B_DIRLEN 8 /* 書籍ディレクトリー名 */ #define B_DPOSLEN_EPW 4 /* ディレクトリー位置(EPWING) */ #define B_INFBLEN_EPW 2 /* 管理情報記録位置(EPWING) */ #define B_APPLEN_EPW 4 /* 実装定義(EPWING) */ #define B_ZGAILEN_EPW 32 /* 全角外字ファイル名(EPWING) */ #define B_HGAILEN_EPW 32 /* 半角外字ファイル名(EPWING) */ /* (EPWING2以降、以下書籍数だけくり返し) */ #define B2_RSV1LEN 4 /* 不明 */ #define B2_BKFILELEN 8 /* 本文ファイル名称 */ #define B2_PAD1LEN 16 /* 不明 */ #define B2_STFILELEN 8 /* ストリームファイル名称 */ #define B2_PAD2LEN 16 /* 不明 */ #define B2_RSV2LEN 4 /* 不明 */ #define B2_PAD3LEN 108 /* 不明 */ /* * カタログヘッダー */ typedef struct hdr_t { uchr books[C_BOOKSLEN]; uchr cdtype[C_CDTYPELEN]; uchr select[C_SELECTLEN]; uchr reserved[C_RSVLEN]; } HDR_T; /* * カタログ内容(電子ブック) */ typedef struct eb_t { uchr booktype[B_BKTYPELEN]; uchr title[B_TTLLEN_EB]; uchr directory[B_DIRLEN]; } EB_T; /* * カタログ内容(EPWING) */ typedef struct epw_t { uchr booktype[B_BKTYPELEN]; uchr title[B_TTLLEN_EPW]; uchr directory[B_DIRLEN]; uchr dirpos[B_DPOSLEN_EPW]; uchr infoblock[B_INFBLEN_EPW]; uchr appdef[B_APPLEN_EPW]; uchr zgaijifile[B_ZGAILEN_EPW]; uchr hgaijifile[B_HGAILEN_EPW]; } EPW_T; /* * カタログ内容(EPWING2以降) */ typedef struct epw2_t { uchr reserved1[B2_RSV1LEN]; uchr bookfile[B2_BKFILELEN]; uchr pad1[B2_PAD1LEN]; uchr streamfile[B2_STFILELEN]; uchr pad2[B2_PAD2LEN]; uchr reserved2[B2_RSV2LEN]; uchr pad3[B2_PAD3LEN]; } EPW2_T; /* * テキストファイルのタグ */ #define EB_ID "EB" #define EPW_ID "EPWING" #define CAT_ENTRY "[Catalog]" #define CTAG_FILENAME "FileName" #define CTAG_BOOKS "Books" #define CTAG_CDTYPE "Type" #define CTAG_SELECT "BookSelect" #define CTAG_RESERVED "Reserved" #define BOOK_ENTRY "[Book]" #define BTAG_BOOKTYPE "BookType" #define BTAG_TITLE "Title" #define BTAG_DIRECTORY "Directory" #define BTAG_DIRPOS "DirPos" #define BTAG_INFOBLOCK "InfoBlock" #define BTAG_APPDEF "AppDef" #define BTAG_ZGAIJIFILE "ZenGaiji" #define BTAG_HGAIJIFILE "HanGaiji" #define B2TAG_RSV1 "Reserved1" #define B2TAG_BKFILE "BookFile" #define B2TAG_PAD1 "Padding1" #define B2TAG_STFILE "StreamFile" #define B2TAG_PAD2 "Padding2" #define B2TAG_RSV2 "Reserved2" #define B2TAG_PAD3 "Padding3" /* * 処理済みマスク */ #define M_FILENAME 0x00000001L #define M_BOOKS 0x00000002L #define M_CDTYPE 0x00000004L /* 必須 */ #define M_SELECT 0x00000008L #define M_RESERVED 0x00000010L #define M_BOOKTYPE 0x00000020L /* 必須 */ #define M_TITLE 0x00000040L /* 必須 */ #define M_DIRECTORY 0x00000080L /* 必須 */ #define M_DIRPOS 0x00000100L #define M_INFOBLOCK 0x00000200L #define M_APPDEF 0x00000400L #define M_ZGAIJIFILE 0x00000800L #define M_HGAIJIFILE 0x00001000L #define M_RESERVED1 0x00002000L #define M_BOOKFILE 0x00004000L #define M_PADDING1 0x00008000L #define M_STREAMFILE 0x00010000L #define M_PADDING2 0x00020000L #define M_RESERVED2 0x00040000L #define M_PADDING3 0x00080000L /* * getstr()の処理方法 */ #define F_NUL 0 /* 余りを0x00で埋める */ #define F_SPACE 1 /* 余りをスペースで埋める */ int proctype = DUMP; int type; int line; char *catalog; char *txtfile; uchr catbuf[BLKSIZ * 2]; uchr epw2buf[BLKSIZ]; uchr buf[BUFSIZ]; int EBGmode = 0; int main(); void usage(); int dump(); uchr *bookkind(); int guess(); int nonzero(); void outhex(); void outstr(); void outjstr(); int undump(); uchr *getline(); uchr *getvalue(); int gethex(); int hexdigit(); int getstr(); int getjstr(); int main(ac, av) int ac; char **av; { int ret; ac--, av++; while (ac > 0 && **av == '-') { switch (av[0][1]) { case 'g': case 'G': EBGmode = 1; break; case 'd': case 'D': proctype = DUMP; break; case 'u': case 'U': proctype = UNDUMP; ac--, av++; if (ac <= 0) usage(); txtfile = *av; break; default: usage(); } ac--, av++; } if (ac != 1) usage(); catalog = *av; switch (proctype) { case DUMP: ret = dump(catalog); break; case UNDUMP: ret = undump(txtfile, catalog); break; } 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", progname); fprintf(stderr, " [-g] [-d] [-u <テキストファイル>] <カタログファイル>\n\n"); fprintf(stderr, "オプション:\n"); fprintf(stderr, " -g: EBG 専用モードにする\n"); fprintf(stderr, " -d: カタログファイルを標準出力にダンプする\n"); fprintf(stderr, " -u: テキストファイルをカタログファイルに変換する\n"); exit(1); } int dump(catalog) char *catalog; { int fd, i, num; HDR_T *hdr; EB_T *eb; EPW_T *epw; EPW2_T *epw2; struct stat st; if (stat(catalog, &st) < 0) { fprintf(stderr, "%s の情報が取得できません\n", catalog); return ERR; } if (st.st_size < 0 || st.st_size > BLKSIZ * 2) { fprintf(stderr, "カタログサイズが異常です\n"); return ERR; } if ((fd = open(catalog, O_RDONLY|O_BINARY)) < 0) { fprintf(stderr, "%s がオープンできません\n", catalog); return ERR; } if (read(fd, (char *)catbuf, st.st_size) < st.st_size) { fprintf(stderr, "ファイルの読み込みに失敗しました\n"); close(fd); return ERR; } close(fd); hdr = (HDR_T *)catbuf; num = (hdr->books[0] << 8) + hdr->books[1]; type = hdr->cdtype[1]; printf("; 電子ブック/EPWING カタログ内容"); printf(" (generated by %s v%s)\n\n", progname, version); printf("%s\n", CAT_ENTRY); printf("%-11s= %s\n", CTAG_FILENAME, catalog); if (type == EB) printf("%-11s= %s\n", CTAG_CDTYPE, EB_ID); else printf("%-11s= %s%d\n", CTAG_CDTYPE, EPW_ID, type); printf("%-11s= %d\n", CTAG_BOOKS, num); if (hdr->select[0] == 0x01) { printf("%-11s= %d\n", CTAG_SELECT, (hdr->select[1] >> 4) * 10 + (hdr->select[1] & 0x0f)); } if (type >= EPWING4 || nonzero(hdr->reserved, C_RSVLEN)) { printf("%-11s= ", CTAG_RESERVED); outhex(hdr->reserved, C_RSVLEN); if (type >= EPWING4) { printf(" (HD利用:%s, NETWORK利用:%s)", (hdr->reserved[2] & 0x10)? "許可": "禁止", (hdr->reserved[2] & 0x01)? "許可": "禁止"); } printf("\n"); } printf("\n"); if (type == EB) { eb = (EB_T *)(catbuf + sizeof(HDR_T)); for (i = 0; i < num; i++) { printf("%s\n", BOOK_ENTRY); printf("%-11s= ", BTAG_BOOKTYPE); outhex(eb->booktype, B_BKTYPELEN); printf("\n"); printf("%-11s= \"", BTAG_TITLE); if (!EBGmode) { outjstr(eb->title, B_TTLLEN_EB); } else { outstr(eb->title, B_TTLLEN_EB); } printf("\"\n"); printf("%-11s= \"", BTAG_DIRECTORY); outstr(eb->directory, B_DIRLEN); printf("\"\n"); printf("\n"); eb++; } } else { epw = (EPW_T *)(catbuf + sizeof(HDR_T)); epw2 = (EPW2_T *)((uchr *)epw + num * sizeof(EPW_T)); for (i = 0; i < num; i++) { printf("%s\n", BOOK_ENTRY); printf("%-11s= ", BTAG_BOOKTYPE); outhex(epw->booktype, B_BKTYPELEN); printf(" (%02X:%s, %02X:EPWING%d)\n", epw->booktype[0], bookkind(epw->booktype), epw->booktype[1], epw->booktype[1]); printf("%-11s= \"", BTAG_TITLE); if (!EBGmode) { outjstr(epw->title, B_TTLLEN_EPW); } else { outstr(epw->title, B_TTLLEN_EPW); } printf("\"\n"); printf("%-11s= \"", BTAG_DIRECTORY); outstr(epw->directory, B_DIRLEN); printf("\"\n"); if (nonzero(epw->dirpos, B_DPOSLEN_EPW)) { printf("%-11s= ", BTAG_DIRPOS); outhex(epw->dirpos, B_DPOSLEN_EPW); printf("\n"); } if (nonzero(epw->infoblock, B_INFBLEN_EPW)) { printf("%-11s= ", BTAG_INFOBLOCK); outhex(epw->infoblock, B_INFBLEN_EPW); printf("\n"); } if (nonzero(epw->appdef, B_APPLEN_EPW)) { printf("%-11s= ", BTAG_APPDEF); outhex(epw->appdef, B_APPLEN_EPW); printf("\n"); } if (nonzero(epw->zgaijifile, B_ZGAILEN_EPW)) { printf("%-11s= \"", BTAG_ZGAIJIFILE); outstr(epw->zgaijifile, B_ZGAILEN_EPW); printf("\"\n"); } if (nonzero(epw->hgaijifile, B_HGAILEN_EPW)) { printf("%-11s= \"", BTAG_HGAIJIFILE); outstr(epw->hgaijifile, B_HGAILEN_EPW); printf("\"\n"); } if (type >= EPWING2) { if (nonzero(epw2->bookfile, B2_BKFILELEN)) { printf("%-11s= \"", B2TAG_BKFILE); outstr(epw2->bookfile, B2_BKFILELEN); printf("\"\n"); } if (nonzero(epw2->streamfile, B2_STFILELEN)) { printf("%-11s= \"", B2TAG_STFILE); outstr(epw2->streamfile, B2_STFILELEN); printf("\"\n"); } if (nonzero(epw2->reserved1, B2_RSV1LEN)) { printf("%-11s= ", B2TAG_RSV1); outhex(epw2->reserved1, B2_RSV1LEN); printf("\n"); } if (nonzero(epw2->reserved2, B2_RSV2LEN)) { printf("%-11s= ", B2TAG_RSV2); outhex(epw2->reserved2, B2_RSV2LEN); printf("\n"); } if (nonzero(epw2->pad1, B2_PAD1LEN)) { printf("%-11s= ", B2TAG_PAD1); outhex(epw2->pad1, B2_PAD1LEN); printf("\n"); } if (nonzero(epw2->pad2, B2_PAD2LEN)) { printf("%-11s= ", B2TAG_PAD2); outhex(epw2->pad2, B2_PAD2LEN); printf("\n"); } if (nonzero(epw2->pad3, B2_PAD3LEN)) { printf("%-11s= ", B2TAG_PAD3); outhex(epw2->pad3, B2_PAD3LEN); printf("\n"); } } printf("\n"); epw++; epw2++; } } return OK; } uchr * bookkind(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 "類語辞典"; case 0xf0: return "ストリーム"; default: return "不明"; } } int nonzero(p, len) uchr *p; int len; { while (len--) if (*p++) return TRUE; return FALSE; } void outhex(p, len) uchr *p; int len; { while (len--) printf("%02X", *p++); } void outstr(p, len) uchr *p; int len; { uchr *pend; pend = p + len; while (pend > p && (pend[-1] == '\0' || pend[-1] == ' ')) pend--; while (p < pend) { if (*p >= 0x20 && *p <= 0x7f) putchar(*p); else if (*p == '"' || *p == '\\') printf("\\%c", *p); else if (*p == '\0') printf("\\0"); else printf("\\x%02X", *p); p++; } } void outjstr(p, len) uchr *p; int len; { int c1, c2; uchr *pend; pend = p + len; while (pend >= p + 2 && (pend[-1] == '\0' && pend[-2] == '\0' || pend[-1] == 0x21 && pend[-2] == 0x21)) pend -= 2; #ifdef EUC while (p < pend) { putchar(*p | 0x80); p++; } #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; putchar(c1); putchar(c2); } #endif } int undump(txtfile, catalog) char *txtfile, *catalog; { int fd, i, st, num, len, err; long mask; uchr *p, *t, *u; FILE *fp; HDR_T *hdr; EB_T *eb; EPW_T *epw; EPW2_T *epw2; if ((fp = fopen(txtfile, "r")) == NULL) { fprintf(stderr, "%s がオープンできません\n", txtfile); return ERR; } memset(catbuf, '\0', BLKSIZ * 2); memset(epw2buf, '\0', BLKSIZ); err = 0; line = 0; if (getline(buf, fp) == NULL || strncmp(buf, CAT_ENTRY, strlen(CAT_ENTRY))) { fprintf(stderr, "ERR: 項目 %s がありません\n", CAT_ENTRY); fclose(fp); return ERR; } type = EB; st = 0; hdr = (HDR_T *)catbuf; mask = 0L; while (getline(buf, fp) != NULL && *buf != '[') { if ((p = getvalue(buf)) == NULL) { fprintf(stderr, "ERR: line %d: 構文に誤りがあります\n", line); err++; continue; } if (!strcmp(buf, CTAG_FILENAME)) { if ((mask & M_FILENAME) != 0) goto ctag_dup; /* * ファイル名の情報は使わないので読み飛ばす */ mask |= M_FILENAME; } else if (!strcmp(buf, CTAG_BOOKS)) { if ((mask & M_BOOKS) != 0) goto ctag_dup; /* * 書籍数の情報は使わないので読み飛ばす */ mask |= M_BOOKS; } else if (!strcmp(buf, CTAG_CDTYPE)) { len = strlen(EPW_ID); if ((mask & M_BOOKTYPE) != 0) goto ctag_dup; if (!strcmp(p, EB_ID)) { type = EB; } else if (!strncmp(p, EPW_ID, len) && p[len] >= '1' && p[len] <= '9' && p[len+1] == '\0') { type = EPWING + p[len] - '1'; } else { fprintf(stderr, "ERR: line %d: %s の値に誤りがあります(%s)\n", line, CTAG_CDTYPE, p); fclose(fp); return ERR; } hdr->cdtype[1] = type; mask |= M_BOOKTYPE; } else if (!strcmp(buf, CTAG_SELECT)) { if ((mask & M_SELECT) != 0) goto ctag_dup; st = 0; while (isdigit(*p)) { st = st * 10 + *p - '0'; p++; } if (*p == '\0' && i > 0) { hdr->select[0] = 0x01; hdr->select[1] = ((st / 10) << 4) + (st % 10); } else { fprintf(stderr, "ERR: line %d: %s の値に誤りがあります(%s)\n", line, CTAG_SELECT, p); fclose(fp); return ERR; } mask |= M_SELECT; } else if (!strcmp(buf, CTAG_RESERVED)) { if ((mask & M_RESERVED) != 0) goto ctag_dup; mask |= M_RESERVED; if (gethex(hdr->reserved, p, C_RSVLEN) == ERR) goto ctag_invalid; } else { fprintf(stderr, "ERR: line %d: 不明のタグです(%s)\n", line, buf); err++; continue; } continue; ctag_dup: fprintf(stderr, "ERR: line %d: タグが二重定義されています(%s)\n", line, buf); err++; continue; ctag_invalid: fprintf(stderr, "ERR: line %d: 値が不正です(%s)\n", line, p); err++; continue; } if ((mask & M_BOOKTYPE) == 0) { fprintf(stderr, "ERR: line %d: %s が見つかりませんでした\n", line, CTAG_CDTYPE); err++; } if (type == EB) { eb = (EB_T *)(catbuf + sizeof(HDR_T)); } else { epw = (EPW_T *)(catbuf + sizeof(HDR_T)); epw2 = (EPW2_T *)epw2buf; } num = 0; while (*buf == '[') { if (strncmp(buf, BOOK_ENTRY, strlen(BOOK_ENTRY))) { fprintf(stderr, "ERR: line %d: 不明な項目です(%s)\n", line, buf); err++; while (getline(buf, fp) != NULL && *buf != '[') ; if (*buf == '\0') break; continue; } if (type == EB && (uchr *)&eb[1] >= catbuf + BLKSIZ || type > EB && (uchr *)&epw[1] >= catbuf + BLKSIZ) { fprintf(stderr, "ERR: line %d: 項目 %s の個数が多すぎます\n", line, BOOK_ENTRY); err++; break; } mask = 0; while (getline(buf, fp) != NULL && *buf != '[') { if ((p = getvalue(buf)) == NULL) { fprintf(stderr, "ERR: line %d: 構文に誤りがあります\n", line); err++; continue; } if (!strcmp(buf, BTAG_BOOKTYPE)) { if ((mask & M_BOOKTYPE) != 0) goto btag_dup; mask |= M_BOOKTYPE; t = (type == EB)? eb->booktype: epw->booktype; if (gethex(t, p, B_BKTYPELEN) == ERR) goto btag_invalid; } else if (!strcmp(buf, BTAG_TITLE)) { if ((mask & M_TITLE) != 0) goto btag_dup; mask |= M_TITLE; if (type == EB) { t = eb->title; len = B_TTLLEN_EB; } else { t = epw->title; len = B_TTLLEN_EPW; } if (!EBGmode) { if (getjstr(t, p, len) == ERR) goto btag_invalid; } else { if (getstr(t, p, len) == ERR) goto btag_invalid; } } else if (!strcmp(buf, BTAG_DIRECTORY)) { if ((mask & M_DIRECTORY) != 0) goto btag_dup; mask |= M_DIRECTORY; t = (type == EB)? eb->directory: epw->directory; if (getstr(t, p, B_DIRLEN, F_SPACE) == ERR) goto btag_invalid; u = t; for (i = 0; i < num; i++) { u -= (type == EB)? sizeof(EB_T): sizeof(EPW_T); if (!memcmp(t, u, B_DIRLEN)) { fprintf(stderr, "ERR: line %d: %s の値が重複しています(%s)\n", line, buf, p); err++; break; } } } else if (!strcmp(buf, BTAG_DIRPOS)) { if (type < EPWING) goto btag_epwonly; if ((mask & M_DIRPOS) != 0) goto btag_dup; mask |= M_DIRPOS; if (gethex(epw->dirpos, p, B_DPOSLEN_EPW) == ERR) goto btag_invalid; } else if (!strcmp(buf, BTAG_INFOBLOCK)) { if (type < EPWING) goto btag_epwonly; if ((mask & M_INFOBLOCK) != 0) goto btag_dup; mask |= M_INFOBLOCK; if (gethex(epw->infoblock, p, B_INFBLEN_EPW) == ERR) goto btag_invalid; } else if (!strcmp(buf, BTAG_APPDEF)) { if (type < EPWING) goto btag_epwonly; if ((mask & M_APPDEF) != 0) goto btag_dup; mask |= M_APPDEF; if (gethex(epw->appdef, p, B_APPLEN_EPW) == ERR) goto btag_invalid; } else if (!strcmp(buf, BTAG_ZGAIJIFILE)) { if (type < EPWING) goto btag_epwonly; if ((mask & M_ZGAIJIFILE) != 0) goto btag_dup; mask |= M_ZGAIJIFILE; if (getstr(epw->zgaijifile, p, B_ZGAILEN_EPW, F_NUL) == ERR) goto btag_invalid; } else if (!strcmp(buf, BTAG_HGAIJIFILE)) { if (type < EPWING) goto btag_epwonly; if ((mask & M_HGAIJIFILE) != 0) goto btag_dup; mask |= M_HGAIJIFILE; if (getstr(epw->hgaijifile, p, B_HGAILEN_EPW, F_NUL) == ERR) goto btag_invalid; } else if (!strcmp(buf, B2TAG_RSV1)) { if (type < EPWING2) goto btag_epw2only; if ((mask & M_RESERVED1) != 0) goto btag_dup; mask |= M_RESERVED1; if (gethex(epw2->reserved1, p, B2_RSV1LEN) == ERR) goto btag_invalid; } else if (!strcmp(buf, B2TAG_BKFILE)) { if (type < EPWING2) goto btag_epw2only; if ((mask & M_BOOKFILE) != 0) goto btag_dup; mask |= M_BOOKFILE; if (getstr(epw2->bookfile, p, B2_BKFILELEN, F_SPACE) == ERR) goto btag_invalid; } else if (!strcmp(buf, B2TAG_PAD1)) { if (type < EPWING2) goto btag_epw2only; if ((mask & M_PADDING1) != 0) goto btag_dup; mask |= M_PADDING1; if (gethex(epw2->pad1, p, B2_PAD1LEN) == ERR) goto btag_invalid; } else if (!strcmp(buf, B2TAG_STFILE)) { if (type < EPWING2) goto btag_epw2only; if ((mask & M_STREAMFILE) != 0) goto btag_dup; mask |= M_STREAMFILE; if (getstr(epw2->streamfile, p, B2_STFILELEN, F_SPACE) == ERR) goto btag_invalid; } else if (!strcmp(buf, B2TAG_PAD2)) { if (type < EPWING2) goto btag_epw2only; if ((mask & M_PADDING2) != 0) goto btag_dup; mask |= M_PADDING2; if (gethex(epw2->pad2, p, B2_PAD2LEN) == ERR) goto btag_invalid; } else if (!strcmp(buf, B2TAG_RSV2)) { if (type < EPWING2) goto btag_epw2only; if ((mask & M_RESERVED2) != 0) goto btag_dup; mask |= M_RESERVED2; if (gethex(epw2->reserved2, p, B2_RSV2LEN) == ERR) goto btag_invalid; } else if (!strcmp(buf, B2TAG_PAD3)) { if (type < EPWING2) goto btag_epw2only; if ((mask & M_PADDING3) != 0) goto btag_dup; mask |= M_PADDING3; if (gethex(epw2->pad3, p, B2_PAD3LEN) == ERR) goto btag_invalid; } else { fprintf(stderr, "ERR: line %d: 不明のタグです(%s)\n", line, buf); err++; continue; } continue; btag_epwonly: fprintf(stderr, "ERR: line %d: このタグはEPWING専用です(%s)\n", line, buf); err++; continue; btag_epw2only: fprintf(stderr, "ERR: line %d: このタグはEPWING2以降専用です(%s)\n", line, buf); err++; continue; btag_dup: fprintf(stderr, "ERR: line %d: タグが二重定義されています(%s)\n", line, buf); err++; continue; btag_invalid: fprintf(stderr, "ERR: line %d: 値が不正です(%s)\n", line, p); err++; continue; } if (type >= EPWING && (mask & M_BOOKTYPE) == 0) { fprintf(stderr, "ERR: line %d: %s が見つかりませんでした\n", line, BTAG_BOOKTYPE); err++; } if ((mask & M_TITLE) == 0) { fprintf(stderr, "ERR: line %d: %s が見つかりませんでした\n", line, BTAG_TITLE); err++; } if ((mask & M_DIRECTORY) == 0) { fprintf(stderr, "ERR: line %d: %s が見つかりませんでした\n", line, BTAG_DIRECTORY); err++; } if (type >= EPWING && (mask & M_INFOBLOCK) == 0) { if (epw->booktype[0] != 0xf0) { /* * ストリーム書籍以外なら * 書籍管理情報ブロックは * 第1ブロックと仮定する */ epw->infoblock[1] = 0x01; } } if (type == EB) { eb++; } else { epw++; epw2++; } num++; } hdr->books[0] = (num >> 8) & 0xff; hdr->books[1] = num & 0xff; if (st > num) { fprintf(stderr, "ERR: %s の値が書籍数を超えています\n", CTAG_SELECT); err++; } if (type >= EPWING2) memcpy((char *)epw, epw2buf, sizeof(EPW2_T) * num); fclose(fp); if (err) return ERR; if ((fd = open(catalog, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0644)) < 0) { fprintf(stderr, "%s が作成できません\n", catalog); return ERR; } len = BLKSIZ; if (type >= EPWING2) { if (sizeof(HDR_T) + (sizeof(EPW_T) + sizeof(EPW2_T)) * num > BLKSIZ) len = BLKSIZ * 2; } if (write(fd, (char *)catbuf, len) != len) { fprintf(stderr, "書き込みに失敗しました\n"); close(fd); return ERR; } close(fd); return OK; } uchr * getline(buf, fp) uchr *buf; FILE *fp; { for (;;) { if (fgets(buf, BUFSIZ, fp) == NULL) { *buf = '\0'; return NULL; } line++; if (*buf != '\0' && *buf != '\n' && *buf != ';') break; } buf[strlen(buf) - 1] = '\0'; return buf; } uchr * getvalue(buf) uchr *buf; { uchr *p, *q; p = buf; while (*p && *p != '=' && *p != ' ' && *p != '\t') p++; q = p; while (*p == ' ' || *p == '\t') p++; if (*p != '=') return NULL; *q = '\0'; p++; while (*p == ' ' || *p == '\t') p++; q = p; if (*q == '"') { q++; while (*q && *q != '"') { if (*q == '\\' && q[1]) q++; q++; } if (*q != '"') return NULL; q++; } else { while (*q && *q != ' ' && *q != '\t') q++; } *q = '\0'; return p; } int gethex(buf, str, len) uchr *buf, *str; int len; { while (len-- > 0) { if (!isxdigit(str[0]) || !isxdigit(str[1])) break; *buf = hexdigit(*str++) << 4; *buf |= hexdigit(*str++); buf++; } if (*str != '\0') return ERR; while (len-- > 0) *buf++ = '\0'; return OK; } int hexdigit(c) int c; { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'F') return c - 'A' + 10; else if (c >= 'a' && c <= 'f') return c - 'a' + 10; return -1; } int getstr(buf, str, len, type) uchr *buf, *str; int len, type; { if (*str++ != '"') return ERR; while (len > 0) { if (*str == '\0') return ERR; if (*str == '"') break; if (*str != '\\') { *buf++ = *str++; len--; continue; } str++; if (*str == '0') { *buf++ = '\0'; str++; } else if (*str == 'x' || *str == 'X') { str++; if (gethex(buf, str, 1) == ERR) return ERR; buf++; str += 2; } else { *buf++ = *str++; } len--; } if (*str != '"') return ERR; if (type == F_NUL) { while (len-- > 0) *buf++ = '\0'; } else { while (len-- > 0) *buf++ = ' '; } return OK; } int getjstr(buf, str, len) uchr *buf, *str; int len; { int c1, c2; if (*str++ != '"') return ERR; #ifdef EUC while (len > 0) { if (*str == '\0') return ERR; if (*str == '"') break; if (*str < 0xa1 || *str > 0xfe || str[1] < 0xa1 || str[1] > 0xfe) return ERR; *buf++ = *str++ & 0x7f; *buf++ = *str++ & 0x7f; len -= 2; } #endif #ifdef SJIS while (len > 0) { if (*str == '\0') return ERR; if (*str == '"') break; c1 = *str++; c2 = *str++; if (c1 < 0x81 || c1 > 0x9f && c1 < 0xe0 || c1 > 0xef) return ERR; if (c1 > 0x9f) c1 -= 0x40; c1 += c1; if (c2 <= 0x9e) { c1 -= 0xe1; if (c2 >= 0x80) c2 -= 1; c2 -= 0x1f; } else { c1 -= 0xe0; c2 -= 0x7e; } *buf++ = c1; *buf++ = c2; len -= 2; } #endif if (*str != '"') return ERR; while (len-- > 0) *buf++ = '\0'; return OK; } epwutil-1.1.orig/catdump.man0100644000175000017500000002346707074542637015506 0ustar mhattamhatta名称 catdump - 電子ブック/EPWINGのカタログをダンプ/アンダンプする バージョン 1.1 - 2000/04/11 形式 catdump [-g] [-d] <カタログファイル> catdump [-g] -u <テキストファイル> <カタログファイル> オプション -g: EBG 専用モードで起動する。 -d: <カタログファイル>の内容をテキストに変換して標準出力に書き出 す(標準) -u: <テキストファイル>の内容をカタログ形式に変換して<カタログフ ァイル>に書き出す <カタログファイル> 電子ブック/EPWINGのカタログファイル(catalogまたはcatalogs) <テキストファイル> catdumpで出力した形式のテキストファイル 使用例 DドライブのEPWING CD-ROMにあるカタログをテキストに変換してcatalog.txt に書き出す(MS-DOS) C> catdump d:\catalogs > catlogs.txt catalogs.txtの内容をカタログ形式に変換してc:\dic\catalogsに書き出す (MS-DOS) C> catdump -u catalogs.txt c:\dic\catalogs 説明 電子ブックやEPWINGのCD-ROMのトップディレクトリーには、CD-ROMにどんな 書籍が含まれているかを示すカタログファイルが置かれている。カタログフ ァイルは電子ブックではcatalog、EPWINGではcatalogsという名前になって いる。catdumpはこのカタログファイルの内容をテキストデータに変換した り、テキストデータからカタログファイルを生成したりする。 catdumpを使うと、カタログファイルから不要な書籍を削除したり、複数の カタログファイルを統合したりすることが可能だ。catdumpはEBXAのロゴの ある電子ブック(1994年以降のもの)とEPWING V1〜V4に対応している。V5に ついては動作確認を行っていない。 catdumpで電子ブック版広辞苑のカタログファイルをダンプした結果が次の 出力だ。 C> catdump d:\catalog ; 電子ブック/EPWING カタログ内容 (generated by catdump v1.0) [Catalog] FileName = d:\catalog Type = EB Books = 2 [Book] Title = "広辞苑 第四版 電子ブック版" BookType = 0100 Directory = "KOUJIEN" [Book] Title = "付属資料" BookType = 0200 Directory = "FUROKU" 先頭の[Catalog]というブロックには、カタログのヘッダー情報が含まれる。 ここではカタログ形式が電子ブック(EB)であること、カタログに含まれる書 籍数が2であることが示されている。 それ以降には[Book]というブロックが書籍数だけ続いている。ここには各書 籍のタイトル、書籍種別、書籍本体(電子ブックの場合はstartというファイ ル)が置かれているディレクトリー名の情報がある。書籍種別のところには、 電子ブックの場合は書籍の順序番号が書かれているようだが、詳しいことは わからない。 以下はEPWING版広辞苑のカタログファイルをダンプした結果だ。 C> catdump d:\catalogs ; 電子ブック/EPWING カタログ内容 (generated by catdump v1.0) [Catalog] FileName = d:\catalogs Type = EPWING2 Books = 4 BookSelect = 4 [Book] BookType = 0002 (00:国語辞典, 02:EPWING2) Title = "広辞苑 第四版" Directory = "KOUJIEN" InfoBlock = 0001 ZenGaiji = "GA16FULLGA24FULLGA30FULLGA48FULL" HanGaiji = "GA16HALFGA24HALFGA30HALFGA48HALF" BookFile = "HONMON" Reserved1 = 000B0000 [Book] BookType = 0001 (00:国語辞典, 01:EPWING1) Title = "付属資料" Directory = "FUROKU" InfoBlock = 0001 ZenGaiji = "GA16FULLGA24FULLGA30FULLGA48FULL" HanGaiji = "GA16HALFGA24HALFGA30HALFGA48HALF" [Book] BookType = F002 (F0:ストリーム, 02:EPWING2) Title = "「広辞苑」紹介" Directory = "GUIDE" StreamFile = "PLAY" Reserved1 = 00100000 [Book] BookType = F002 (F0:ストリーム, 02:EPWING2) Title = "書籍選択画面" Directory = "BKSLCT" StreamFile = "SELECT" Reserved1 = 00100000 [Catalog]の情報からは、カタログの形式がEPWING V2(EPWING2)であること、 書籍数が4であること、EPWING V2対応の検索ソフトで使われる書籍選択画面 が4番めの書籍であることがわかる。 先頭の書籍に対応する[Book]項目からは、タイトル、EPWING書籍種別(種別 は国語辞典、形式はEPWING2)、書籍本体(EPWINGの場合はhonmonなど)が置か れたディレクトリー(KOUJIEN)、書籍本体の書籍情報ブロック番号、各種外 字(gaijiディレクトリーにある)のファイル名、書籍本体のファイル名、そ の他の情報がわかる。 [Catalog]項目のタグ名とその意味は次の通りだ。括弧でEPWINGのバージョ ンが書かれているものは、EPWINGのそのバージョン以降でしか使われない。 FileName カタログファイルのパス名 Books カタログに含まれる書籍数 Type カタログ形式(電子ブックまたはEPWING) BookSelect 書籍選択画面の書籍番号(EPWING V2) Reserved 不明(EPWING V4以降ではハードディスクインストールや ネットワークインストールの可否が含まれる) [Book]項目には次のようなタグがある。 BookType 書籍種別(電子ブックの場合は詳細不明) Title 書籍名称(電子ブックは15文字、EPWINGは40文字まで) Directory 書籍本体の置かれたディレクトリー DirPos ディレクトリー位置(詳細は不明だが、ハードディスクに インストールした書籍の場合は無関係のようだ) 以下はEPWINGでのみ使われる[Book]のタグだ。 InfoBlock 書籍本体にある書籍情報のブロック番号 AppDef アプリケーション定義の情報(詳細不明) ZenGaiji 16/24/30/48ドットの全角外字ファイル名(8バイト×4) HanGaiji 16/24/30/48ドットの半角外字ファイル名(8バイト×4) 以下はEPWING V2以降で使われる[Book]のタグだ。 Reserved1 詳細不明(EPWING V4以降の圧縮フラグなど?) BookFile 書籍ファイル名(通常はHONMON。HONMON2ならEPWING V4以 降の圧縮ファイルのようだ) Padding1 詳細不明(おそらく空白) StreamFile ストリーム(動画・音声)書籍ファイル名 Padding2 詳細不明(おそらく空白) Reserved2 詳細不明 Padding3 詳細不明(おそらく空白) カタログファイルをダンプ/アンダンプして新しいカタログファイルを作る 場合の指針を以下に示す。 カタログファイルからある書籍を削除するには、その書籍に対応する[Book] 項目全体を削除し、[Catalog]にある書籍数(Books)と書籍選択画面の書籍番 号(BookSelect)の値を適当に調整してから、catdump -uで新しいカタログフ ァイルを作ればよい。 複数のカタログファイルを統合するには、それらの[Book]項目を適当に並べ、 それに合わせて[Catalog]項目を調整してから、catdump -uで新しいカタロ グファイルを作ればよい。異なるバージョンのEPWINGカタログを統合するこ とも可能であり、その場合は最も高いバージョンを[Catalog]に指定してお く。電子ブックとEPWINGのカタログを統合することはできない。 [Book]項目にある情報のうちあるものは変更してかまわない。Titleを変更 すれば、検索ソフトの書籍名表示が変わる。ただし、Titleには(空白を含め て)2バイト文字しか指定できない。文字数の上限は、電子ブックの場合は15 文字、EPWINGの場合は40文字になっている。Directoryを変更すれば、複数 のカタログを統合するときにディレクトリー名の衝突を避けられるかもしれ ない。EPWINGでは、ZenGaijiとHanGaijiを変更すれば使われる外字ファイル を減らすことができる。たとえばEPWING版広辞苑の外字ファイルは ZenGaiji = "GA16FULLGA24FULLGA30FULLGA48FULL" HanGaiji = "GA16HALFGA24HALFGA30HALFGA48HALF" となっているが、これを ZenGaiji = "GA16FULLGA24FULL" HanGaiji = "GA16HALFGA24HALF" に変更すれば、30ドットと48ドットの外字ファイルは参照されない。 検索ソフトとしてEPWING V1対応のものを利用する場合、[Book]項目にある 情報のうち、EPWING V2以降でのみ必要とされるものは削除してかまわない。 EPWING V2以降の書籍のうちEPWING V1対応の検索ソフトでも読めるものにつ いては、ここには標準的な値しか書かれていない。 エラーメッセージ ダンプ時のエラー <カタログファイル名> の情報が取得できません <カタログファイル名> がオープンできません 指定したパス名のカタログファイルが存在しない。 カタログサイズが異常です カタログファイルのサイズが2048バイト以下でも4096バイトでもない。 誤ったファイルを指定している可能性がある。 ファイルの読み込みに失敗しました ファイルの読み込み時に何らかのエラーが発生した。 アンダンプ時のエラー <テキストファイル名>がオープンできません 存在しないテキストファイルを指定している。 <カタログファイル名> が作成できません 指定されたパス名のカタログファイルが新規作成できない。 書き込みに失敗しました ファイルの書き込み時に何らかのエラーが発生した。 ERR: 項目 [Catalog] がありません カタログ定義の始まりを示す[Catalog]がファイル中にない。 ERR: line <行番号>: 構文に誤りがあります タグと値を区切る「=」がない。 ERR: line <行番号>: Type の値に誤りがあります(<値>) Typeタグの値が次のいずれでもない。 EB, EPWING1, EPWING2, EPWING3, EPWING4, EPWING5 ERR: line <行番号>: BookSelect の値に誤りがあります(<値>) BookSelectタグの値が正の整数でない。 ERR: line <行番号>: 不明のタグです(<タグ名>) タグ名が[Catalog]や[Book]に対して定義されているものでない。 ERR: line <行番号>: タグが二重定義されています(<タグ名>) 1つの項目中で同一のタグが複数回現れた。 ERR: line <行番号>: 値が不正です(<値>) 以下のいずれかに該当した。 ・16進数タグの値が期待した長さでない。 ・16進数タグの値に0〜9、A〜F、a〜f以外の文字が含まれている。 ・文字列タグの値が「"」で囲まれていない。 ・文字列タグの値の長さが上限を超えている。 ・ASCII文字列タグの値にASCII文字、「\0」、「\x??」(2桁の16進数) 以外の文字が含まれている。 ・JIS文字列タグの値にJIS漢字以外の文字が含まれている。 ERR: line <行番号>: Type が見つかりませんでした <行番号>の直前にある[Catalog]項目にType指定がない。 ERR: line <行番号>: 不明な項目です(<項目名>) [Catalog]、[Book]以外の項目名が指定されている。 ERR: line <行番号>: 項目 [Book] の個数が多すぎます 1つのカタログで定義可能な書籍数(電子ブックでは50、EPWINGでは12) を超えている。 ERR: line <行番号>: Directory の値が重複しています(<値>) 異なる書籍に同じDirectoryの値が指定されている。 ERR: line <行番号>: このタグはEPWING専用です(<タグ名>) 電子ブックの書籍に以下のタグが指定されている。 DirPos, InfoBlock, AppDef, ZenGaiji, HanGaiji ERR: line <行番号>: このタグはEPWING2以降専用です(<タグ名>) 電子ブックまたはEPWING1の書籍に以下のタグが指定されている。 BookFile, StreamFile, Reserved1, Reserved2, Padding1, Padding2, Padding3 ERR: line <行番号>: BookType が見つかりませんでした <行番号>の直前にある[Book]項目にBookType指定がない。 ERR: line <行番号>: Title が見つかりませんでした <行番号>の直前にある[Book]項目にTitle指定がない。 ERR: line <行番号>: Directory が見つかりませんでした <行番号>の直前にある[Book]項目にDirectory指定がない。 ERR: BookSelect の値が書籍数を超えています BookSelectに1〜書籍数の範囲外の数値を指定した。 epwutil-1.1.orig/epw.h0100644000175000017500000001045206646727127014311 0ustar mhattamhatta/* * epw.h - 電子ブック/EPWINGユーティリティー ヘッダーファイル * * Written by Junn Ohta (ohta@src.ricoh.co.jp). Public Domain. */ typedef unsigned char uchr; typedef unsigned long ulng; typedef unsigned char byte; typedef unsigned int word; typedef unsigned long dword; #define OK 0 #define ERR (-1) #define FALSE 0 #define TRUE 1 /* * 書籍ブロックサイズ */ #define BLKSIZ 2048 /* * 複合書籍管理情報識別子 */ #define ID_CINFO 0xff /* * 書籍管理情報ブロックの構造 */ #define ITEMS_LEN 2 /* 書籍構成要素数 */ #define RESV1_LEN 2 /* 予備領域1(書籍種別/保護情報) */ #define IDXHNDL_LEN 1 /* インデックス作成情報の取扱法 */ #define RESV2_LEN 11 /* 予備領域2 */ /* (以下構成要素数だけくり返し) */ #define ITEMID_LEN 1 /* 書籍構成要素識別子 */ #define RESV3_LEN 1 /* 予備領域3 */ #define TOPBLK_LEN 4 /* 先頭アドレス(ブロック番号) */ #define BLKS_LEN 4 /* 領域サイズ(ブロック数) */ #define IDXVALID_LEN 1 /* インデックス作成情報有効性 */ #define IDXINFO_LEN 3 /* インデックス作成情報 */ #define RESV4_LEN 2 /* 予備領域4 */ /* (くり返し終わり) */ #define DSPVALID_LEN 1 /* 表示方法初期値情報有効無効フラグ */ #define RESV5_LEN 3 /* 予備領域5 */ #define DSPLIST_LEN 1 /* 一覧表表示 */ #define DSPSTYLE_LEN 1 /* 本文表示法 */ #define RESV6_LEN 10 /* 予備領域6 */ /* * 複合検索管理情報ブロックの構造 */ #define CENTS_LEN 2 /* 複合エントリ数 */ #define CRESV1_LEN 14 /* 予備領域1 */ /* (以下エントリ数だけくり返し) */ #define CITEMS_LEN 1 /* 書籍構成要素数 */ #define CRESV2_LEN 1 /* 予備領域2 */ #define CNAME_LEN 30 /* 検索名称 */ /* (以下要素数だけくり返し) */ #define CITEMID_LEN 1 /* 書籍構成要素識別子 */ #define CRESV3_LEN 1 /* 予備領域3 */ #define CTOPBLK_LEN 4 /* 先頭アドレス(ブロック番号)*/ #define CBLKS_LEN 4 /* 領域サイズ(ブロック数) */ #define CRESV4_LEN 6 /* 予備領域4 */ /* (くり返し終わり) */ /* (くり返し終わり) */ /* * CRESV4_LENはJIS X4081(平成8年11月30日発行の第1刷)によれば5だが、 * 実際の書籍では6になっている。 */ /* * 前方参照定義 */ typedef struct info_t INFO_T; /* 書籍管理情報 */ typedef struct item_t ITEM_T; /* 書籍構成要素 */ typedef struct cinfo_t CINFO_T; /* 複合検索管理情報 */ typedef struct cent_t CENT_T; /* 複合エントリ */ typedef struct citem_t CITEM_T; /* 複合検索書籍構成要素 */ /* * 書籍管理情報 */ struct info_t { word items; /* 登録書籍数 */ byte resv1[RESV1_LEN]; /* 予備領域1 */ byte idxhndl; /* インデックス作成情報の取扱法 */ byte resv2[RESV2_LEN]; /* 予備領域2 */ ITEM_T *item; /* 書籍構成要素 */ byte dspvalid; /* 有効無効フラグ */ byte resv5[RESV5_LEN]; /* 予備領域5 */ byte dsplist; /* 一覧表表示 */ byte dspstyle; /* 本文表示法 */ byte resv6[RESV6_LEN]; /* 予備領域6 */ }; /* * 書籍構成要素 */ struct item_t { byte itemid; /* 書籍構成要素識別子 */ byte resv3[RESV3_LEN]; /* 予備領域3 */ dword topblk; /* 先頭アドレス */ dword blks; /* 領域サイズ */ byte idxvalid; /* インデックス作成情報有効性 */ dword idxinfo; /* インデックス作成情報 */ byte resv4[RESV4_LEN]; /* 予備領域4 */ CINFO_T *cinfo; /* 複合検索管理情報 */ }; /* * 複合検索管理情報 */ struct cinfo_t { word cents; /* 複合エントリ数 */ byte cresv1[CRESV1_LEN]; /* 予備領域1 */ CENT_T *cent; /* 複合エントリ */ }; /* * 複合エントリ */ struct cent_t { byte citems; /* 書籍構成要素数 */ byte cresv2[CRESV2_LEN]; /* 予備領域2 */ byte cname[CNAME_LEN]; /* 検索名称 */ CITEM_T *citem; /* 複合書籍構成要素 */ }; /* * 複合書籍構成要素 */ struct citem_t { uchr citemid; /* 書籍構成要素識別子 */ uchr cresv3[CRESV3_LEN]; /* 予備領域3 */ dword ctopblk; /* 先頭アドレス */ dword cblks; /* 領域サイズ */ uchr cresv4[CRESV4_LEN]; /* 予備領域4 */ }; /* * bread.c */ int open_book(); int close_book(); int locate_block(); int read_block(); long cur_block(); int cur_off(); byte getbyte(); word getword(); dword getdword(); long getbcd(); byte *getbytes(); INFO_T *getinfo(); void freeinfo(); /* * bwrite.c */ int open_newbook(); int close_newbook(); int locate_newblock(); int write_newblock(); long cur_newblock(); int cur_newoff(); int get_error(); void reset_error(); int putbyte(); int putword(); int putdword(); int putbcd(); int putbytes(); int putinfo(); epwutil-1.1.orig/epwutil.doc0100644000175000017500000005764307075276507015540 0ustar mhattamhatta============================================================================ 電子ブック/EPWING活用ユーティリティー EPWUTIL ユーザーズマニュアル ============================================================================ 《目次》 1. EPWUTILとは 2. EPWUTILを利用する前に 3. インストール 3.1 MS-DOS編 3.2 UNIX編 4. 使いかた 4.1 CD-ROM辞書の構造 4.1.1 電子ブック 4.1.2 EPWING 4.2 操作の流れ 4.3 操作例 4.3.1 EPWING版広辞苑第四版をハードディスクにコピーする 4.3.2 電子ブック版広辞苑と研究社新英和・和英中辞典を統合する 5. 制約事項 5.1 処理できないCD-ROM 5.2 動作確認済みCD-ROM 6. 利用条件 7. 原作者 8. 履歴 ---------------------------------------------------------------------------- 1. EPWUTILとは ---------------------------------------------------------------------------- EPWUTILは、電子ブックやEPWING規格のCD-ROM辞書をハードディスクに置いて使 う際に、辞書の有効利用を図るためにCD-ROM辞書の構成ファイルを一部改変する MS-DOS/UNIX用のユーティリティーの集まりです。 ・CD-ROMカタログを編集し、不要な書籍を削除したり、同一規格の複数のCD-ROM カタログを統合したりすることができます。(catdump) ・書籍ファイルから図版・音声などのマルチメディアデータや条件検索・複合検 索のインデックスを削除し、辞書を小さくできます。(squeeze) ・書籍ファイルの構成情報を調べ、辞書を軽量化するための指針を得ることがで きます。(bookinfo) 各ユーティリティーの詳細や利用条件については、それぞれのマニュアルを参照 してください。 なお、bookinfoとsqueezeは、EPWING V4以降の圧縮書籍を含むいくつかの書籍に は対応していません。具体的な内容については「5.制約事項」をご覧ください。 ---------------------------------------------------------------------------- 2. EPWUTILを利用する前に ---------------------------------------------------------------------------- ★この節には、EPWUTILを利用するすべてのユーザーが理解しておくべき注意事 項が書かれています。必ずお読みください。 EPWUTILは、CD-ROMに置いたまま利用するという前提で提供されている辞書製品 をハードディスクにコピーして有効活用するためのユーティリティーです。また、 EPWUTILは辞書データを一部変更します。 これらの行為は著作権法第30条(私的使用のための複製)および第47条の2(プログ ラムの著作物の複製物の所有者による複製等)により、個人の正当な権利として 認められたものです。したがって、辞書製品の利用条件にこれらの行為を禁ずる 旨の一方的な記載があったとしても、その利用条件に従うという利用許諾契約を 別途結んだ場合を除き、必ずしも従う必要はありません。 とはいうものの、辞書データの利用者は著作者の権利をじゅうぶんに尊重する必 要があります。電子化されたデータはコピーが容易で、また情報も劣化しません。 しかも電子ブックやEPWING形式の辞書コンテンツは単なるデータであり、プロテ クトをかけることもできません。したがって、通常の著作物よりもはるかに著作 者の権利が侵害されやすい状態にあるといえるからです。 辞書コンテンツというのは出版社にとってはきわめて貴重な財産です。それにも かかわらず、出版社が自社の権利を防衛するための手段はきわめて少なく、利用 者の良識のみに任されているのが実情です。電子ブックやEPWINGの辞書製品がそ のような危うい状況で提供されていることを、利用者は肝に銘じておく必要があ ります。さもなければ、共通規格による電子出版という基盤そのものが危うくな ってしまうでしょう。 EPWUTILのようなプログラムを利用することは、たとえ正当な権利の行使であっ ても、出版社にとっては自社権利に対する深刻な脅威であると解釈される可能性 があります。利用者はそのことを理解し、正当な権利の範囲から外れるような行 為はかたく慎んでください。 ---------------------------------------------------------------------------- 3. インストール ---------------------------------------------------------------------------- 3.1 MS-DOS編 MS-DOS実行ファイルパッケージには以下のファイルが含まれています。 README 最初に読むファイル epwutil.doc このドキュメント catdump.exe カタログをダンプ/アンダンプするプログラム bookinfo.exe 書籍管理情報を表示するプログラム squeeze.exe 書籍ファイルを軽量化するプログラム catdump.man catdump.exeのマニュアル bookinfo.man bookinfo.exeのマニュアル squeeze.man squeeze.exeのマニュアル 3つの実行ファイルをコマンド検索パスに含まれるいずれかのディレクトリーに コピーしてください。以上でインストールは終わりです。 3.2 UNIX編 UNIX/MS-DOSソースファイルパッケージには以下のファイルが含まれています。 README 最初に読むファイル epwutil.doc このドキュメント catdump.c カタログをダンプ/アンダンプするプログラムソース bookinfo.c 書籍管理情報を表示するプログラムソース squeeze.c 書籍ファイルを軽量化するプログラムソース bread.c bookinfoとsqueezeの共通プログラムソース bwrite.c bookinfoとsqueezeの共通プログラムソース epw.h bookinfoとsqueezeの共通プログラムヘッダーファイル makefile.dos MS-DOS/Turbo C++ 1.0用Makefile makefile.unx UNIX/gcc用Makefile catdump.man catdumpのマニュアル bookinfo.man bookinfoのマニュアル squeeze.man squeezeのマニュアル ソースファイル中の日本語はEUCになっています。プログラムを実行したときの 出力もEUCで行われます。シフトJISの環境でコンパイル・実行する場合は、プロ グラムソースとヘッダーファイルをシフトJISに変換し、さらにmakefile.unxの 「CFLAGS」の行にある「-DEUC」を「-DSJIS」に変更してください。 Cコンパイラーは標準でgccを使うようになっています。別の処理系を利用したい 場合はmakefile.unxの「CC = gcc」の行を適当に変更してください。 準備が終わったら次のコマンドを実行します。 % make -f makefile.unx makeが終了するとカレントディレクトリーにcatdump、bookinfo、squeezeの3つ の実行ファイルができるので、コマンド検索パスに含まれるいずれかのディレク トリーにコピーしてください。以上でインストールは終わりです。 ---------------------------------------------------------------------------- 4. 使いかた ---------------------------------------------------------------------------- 4.1 CD-ROM辞書の構造 ここでは、EPWUTILを利用するための前提知識として、CD-ROM辞書の構造につい て説明します。 4.1.1 電子ブック 電子ブック(EB)は8cm CD-ROMがキャディーに格納された電子出版物の規格です。 計算機で利用するには、CD-ROMをキャディーから取り出してCD-ROMドライブにセ ットする必要があります。電子ブックのデータはISO9660形式で格納されており、 さまざまなOSからファイルとしてアクセスできます。一般的なディレクトリー構 造は以下のようになっています。 /-+- catalog |- book1 ----- start |- book2 ----- start |- ... '- bookN ----- start CD-ROMのトップディレクトリーにはcatalogというファイルがあります。このフ ァイルは書籍一覧で、このCD-ROMの中にどんな書籍があるか、それぞれどのディ レクトリーの下に格納されているかなどの情報が含まれています。book1〜bookN はcatalog中にある各書籍に対応するディレクトリーで、それぞれのディレクト リーにはその下にstartというファイルがあります。startは書籍本体で、ここに は本文やインデックス、図版、外字データなどが含まれています。 CD-ROMのトップディレクトリーや各ディレクトリーにはこれ以外のファイルが含 まれていることもありますが、辞書データをハードディスクにコピーして利用す る場合にはほとんど関係がありません。 EPWUTILで扱えるのは、1994年以降に発売された「EBXA」というロゴのある電子 ブック製品です。なお、このロゴのある製品でも扱えない可能性があります。詳 しくは「5.制約事項」をご覧ください。 4.1.2 EPWING EPWINGは12cm CD-ROMの電子出版物の規格です。電子ブックと同様に、CD-ROMド ライブにセットして利用します。EPWINGの一般的なディレクトリー構造は以下の ようになっています。 /-+- catalogs |- book1 ---+- data ----- honmon | '- gaiji --+- ga16full | |- ... | '- ga48half |- book2 ---+- data ----- honmon | '- gaiji --+- ga16full | |- ... | '- ga48half |- book3 ----- stream --- play |- book4 ----- stream --- select |- ... '- bookN ----- ... CD-ROMのトップディレクトリーにはcatalogsというファイルがあります。このフ ァイルは書籍一覧で、EPWINGのバージョンはいくつか、このCD-ROMの中にどんな 書籍があるか、その書籍はどんな形式のものか、それぞれどのディレクトリーの 下に格納されているかなどの情報が含まれています。book1〜bookNはcatalogs中 にある各書籍に対応するディレクトリーで、それぞれのディレクトリーの下には dataとgaiji、あるいはstreamというディレクトリーがあります。dataの下には honmonというファイル(名前が違うこともある)があり、これが書籍本体になって います。gaijiの下にはさまざまなドット数の外字データファイルが格納されて います。streamというディレクトリーにはEPWING V2で定められたストリーム書 籍が含まれています。ストリーム書籍は動画書籍や書籍選択画面などを実現する ものです。 EPWUTILはEPWING V4以降の圧縮書籍には対応していません。また、それ以外の書 籍でも扱えないものがあります。詳しくは「5.制約事項」をご覧ください。 4.2 操作の流れ CD-ROM辞書をハードディスクに置いて利用するには、CD-ROM辞書と同様のディレ クトリー構造をハードディスク上に再現する必要があります。通常はCD-ROM辞書 の内容を、ディレクトリー構造を保ったまますべてハードディスク上にコピーし て利用しますが、EPWUTILを利用すれば不要なデータをコピーしないですみます。 不要なデータを削減するおおまかな手順は以下のとおりです。具体的な例につい ては次の節で示します。 (1) CD-ROMを眺めてコピーする内容を検討する CD-ROMには複数の書籍が含まれています。またEPWING書籍ではさまざまなド ット数の外字データが含まれています。これらの中で、どの書籍とどの外字 データが必要かを検討します。 (2) カタログ中の書籍を取捨選択する catdumpを使ってCD-ROMカタログをテキストファイルに変換・出力し、その ファイルを編集して不要な書籍を削除します。 (3) カタログ中の外字ファイルを取捨選択する(EPWINGのみ) (1)で残した書籍データに不要な外字ファイルデータがあれば、テキストフ ァイルを編集してそれを削除します。検索ソフトから印刷を行うのでなけれ ば、30ドットや48ドットの外字ファイルは不要です。 (4) 書籍本体中の構成要素を取捨選択する bookinfoを使って、(2)で残した書籍の管理情報を出力し、不要な構成要素 はどれかを検討します。 (5) 取捨選択の結果に従ってファイルをコピーする (2)〜(4)の結果から、残した書籍に対応するディレクトリー構造をハードデ ィスク上に作り、EPWINGであれば残した外字ファイルをコピーします。次に catdumpを使って、(2)〜(3)で編集したテキストファイルからハードディス ク上に新しいカタログファイルを作ります。最後に、書籍本体のデータをハ ードディスクの対応するディレクトリーに、squeezeを使って構成要素を削 減しながら、あるいは削減する構成要素がなければそのまま、コピーします。 なお、検索ソフトによってはハードディスク上の辞書を認識しないものや、辞書 のトップディレクトリーがハードディスクのトップディレクトリーになければ認 識しないものなどがあります。ハードディスク上に置かれた辞書が利用できるか どうかは、個々の検索ソフトの説明書をご覧ください。 4.3 操作例 MS-DOS上でEPWUTILを使った場合の具体的な操作例を示します。 4.3.1 EPWING版広辞苑第四版をハードディスクにコピーする ここでは、DドライブにあるEPWING版広辞苑第四版のCD-ROMをハードディスクの c:\dicの下にコピーするものとします。作業はc:\tmpの下で行います。 このCD-ROMには広辞苑本体、付属資料、広辞苑紹介、書籍選択画面の4つの書籍 が含まれていますが、ここでは広辞苑本体だけをコピーします。また、広辞苑本 体に含まれる各種データのうち、図版や音声といったマルチメディアデータ、条 件検索や複合検索のインデックスは削除します。外字データは16ドットと24ドッ トのものを残し、30ドットと48ドットのものはコピーしません。 CD-ROMの内容を見ると、次のディレクトリーとファイルがあることがわかります。 d:\-+- catalogs |- koujien -+- data ----- honmon | '- gaiji --+- ga16full | |- ga16half | |- ga24full | |- ga24half | |- ga30full | |- ga30half | |- ga48full | '- ga48half |- furoku --+- data ----- honmon | '- gaiji --+- ga16full | |- ga16half | |- ga24full | |- ga24half | |- ga30full | |- ga30half | |- ga48full | '- ga48half |- guide ----- stream --- play '- bkslct ---- stream --- select これをハードディスクのc:\dic以下に次のような構造でコピーします。catalogs はcatdumpで編集し、honmonファイルはsqueezeで軽量化します。それ以外のファ イルはそのままコピーすることになります。 c:\dic\-+- catalogs※ '- koujien -+- data ----- honmon※ '- gaiji --+- ga16full |- ga16half |- ga24full '- ga24half まず、catalogsから広辞苑本体以外の書籍を削除します。c:\tmpの下にcatdump でテキストに変換したカタログを作り、それを編集します。(EBG 形式の辞書の 場合には catdump に -g オプションが必要。以下同様) C> catdump d:\catalogs > c:\tmp\catalogs.txt C> edit c:\tmp\catalogs.txt ; 電子ブック/EPWING カタログ内容 (generated by catdump v1.0) [Catalog] FileName = d:\catalogs Type = EPWING2 Books = 4 BookSelect = 4 [Book] BookType = 0002 (00:国語辞典, 02:EPWING2) Title = "広辞苑 第四版" Directory = "KOUJIEN" InfoBlock = 0001 ZenGaiji = "GA16FULLGA24FULLGA30FULLGA48FULL" HanGaiji = "GA16HALFGA24HALFGA30HALFGA48HALF" BookFile = "HONMON" Reserved1 = 000B0000 [Book] BookType = 0001 (00:国語辞典, 01:EPWING1) Title = "付属資料" Directory = "FUROKU" ... ここでは広辞苑本体以外の書籍は不要なので、対応する[Book]項目をすべて削除 します。これに合わせて[Catalog]項目のBooksの値を1に変更し、BookSelectの 行を削除します。また、広辞苑本体の[Book]項目でZenGaijiとHanGaijiの値を変 更し、30ドットと48ドットの外字が使われないようにします。 変更後の内容は以下のようになるので、上書き保存してエディターを終了します。 ; 電子ブック/EPWING カタログ内容 (generated by catdump v1.0) [Catalog] FileName = d:\catalogs Type = EPWING2 Books = 1 [Book] BookType = 0002 (00:国語辞典, 02:EPWING2) Title = "広辞苑 第四版" Directory = "KOUJIEN" InfoBlock = 0001 ZenGaiji = "GA16FULLGA24FULL" HanGaiji = "GA16HALFGA24HALF" BookFile = "HONMON" Reserved1 = 000B0000 次に、ハードディスクのc:\dicの下に必要なディレクトリー構造を作り、外字フ ァイルをコピーします。 C> mkdir c:\dic\koujien C> mkdir c:\dic\koujien\data C> mkdir c:\dic\koujien\gaiji C> copy d:\koujien\gaiji\ga16* c:\dic\koujien\gaiji C> copy d:\koujien\gaiji\ga24* c:\dic\koujien\gaiji さらに、c:\dicの直下に新しいcatalogsを作ります。 C> catdump -u c:\tmp\catalogs.txt c:\dic\catalogs 最後に、広辞苑本体の書籍ファイルを軽量化しながらc:\dic\koujien\dataの下 にコピーします。この作業には数分かかります。(EBG 形式の辞書の場合には squeeze に -g オプションが必要。以下同様) C> squeeze d:\koujien\data\honmon c:\dic\koujien\data\honmon 以上で終わりです。検索ソフトからc:\dic以下を辞書データとして参照するよう に設定すれば、ハードディスク上に置いた広辞苑が使えるようになります。 4.3.2 電子ブック版広辞苑と研究社新英和・和英中辞典を統合する ここでは、電子ブックの広辞苑と研究社新英和・和英中辞典を統合して、検索ソ フトからは1つのCD-ROMのように見えるようにします。統合された辞書はハード ディスクのc:\dicの下にコピーします。作業はc:\tmpの下で行います。 広辞苑には広辞苑本体と付属資料、研究社新英和・和英中辞典には英和と和英の 書籍が含まれています。ここでは広辞苑の付属資料を除いた3つの書籍をコピー します。また、広辞苑本体や英和、和英に含まれる図版や条件検索、複合検索の インデックスは削除します。 広辞苑、研究社新英和・和英中辞典のCD-ROMを見ると、次のディレクトリーとフ ァイルがあることがわかります。広辞苑のsoundファイルはハードディスク上に 置いて利用できるファイルではありません。またlanguageというファイルはふつ うは使われません。 d:\-+- catalog |- koujien -+- start | '- sound |- furoku ---- start '- language d:\-+- catalog |- eiwa ------ start '- waei ------ start これをハードディスクのc:\dic以下に次のような構造でコピーします。catalog はcatdumpで編集し、各startファイルはsqueezeで軽量化します。 c:\dic\-+- catalog※ |- koujien --- start※ |- eiwa ------ start※ '- waei ------ start※ まず、2つのcatalogを統合し、不要な書籍を削除します。c:\tmpの下にcatdump でテキストに変換したカタログを作り、それを編集します。 (広辞苑CD-ROMをセット) C> catdump d:\catalog > c:\tmp\catalog.txt (新英和・和英中辞典CD-ROMをセット) C> catdump d:\catalog >> c:\tmp\catalog.txt C> edit c:\tmp\catalogs.txt ; 電子ブック/EPWING カタログ内容 (generated by catdump v1.0) [Catalog] FileName = d:\catalog Type = EB Books = 2 [Book] BookType = 0100 Title = "広辞苑 第四版 電子ブック版" Directory = "KOUJIEN" [Book] BookType = 0200 Title = "付属資料" Directory = "FUROKU" ; 電子ブック/EPWING カタログ内容 (generated by catdump v1.0) [Catalog] FileName = d:\catalog Type = EB Books = 2 [Book] BookType = 0100 Title = "研究社 新英和中辞典" Directory = "EIWA" [Book] BookType = 0200 Title = "研究社 新和英中辞典" Directory = "WAEI" ここでは付属資料に対応する[Book]項目と2番めの[Catalog]項目を削除します。 また[Catalog]のBooksの値を3に変更します。BookTypeの値はそのままにしてお いてもよさそうですが、念のため、先頭から0100、0200、0300と並ぶように変更 しておきます。 変更後の内容は以下のようになるので、上書き保存してエディターを終了します。 ; 電子ブック/EPWING カタログ内容 (generated by catdump v1.0) [Catalog] FileName = d:\catalog Type = EB Books = 3 [Book] BookType = 0100 Title = "広辞苑 第四版 電子ブック版" Directory = "KOUJIEN" [Book] BookType = 0200 Title = "研究社 新英和中辞典" Directory = "EIWA" [Book] BookType = 0300 Title = "研究社 新和英中辞典" Directory = "WAEI" 次に、ハードディスクのc:\dicの下に必要なディレクトリー構造を作り、新しい catalogを作ります。 C> mkdir c:\dic\koujien C> mkdir c:\dic\eiwa C> mkdir c:\dic\waei C> catdump -u c:\tmp\catalog.txt c:\dic\catalog 最後に、各書籍ファイルを軽量化しながらハードディスクにコピーします。 (広辞苑CD-ROMをセット) C> squeeze d:\koujien\start c:\dic\koujien\start (新英和・和英中辞典CD-ROMをセット) C> squeeze d:\eiwa\start c:\dic\eiwa\start C> squeeze d:\waei\start c:\dic\waei\start 以上で終わりです。検索ソフトからc:\dic以下を辞書データとして参照するよう に設定すれば、ハードディスク上に置いた広辞苑と研究社新英和・和英中辞典が 1つのCD-ROMのように使えるようになります。 ---------------------------------------------------------------------------- 5. 制約事項 ---------------------------------------------------------------------------- 5.1 処理できないCD-ROM EPWUTILは非公開の情報に基づいて処理を行っているため、電子ブックやEPWING と書かれているCD-ROMでも処理できないことがあります。以下では各ユーティリ ティーについて処理できないCD-ROMとその詳細を挙げておきます。 catdumpは以下のCD-ROMに対応していません。 ・初期の電子ブック パッケージにEBXAでなくEBのロゴが描かれているもの。トップディレクトリ ーにcatalogファイルが存在しないもの、catalogファイルのサイズが2048バ イトを超えているもの。書籍ディレクトリーにstartファイルが存在しない もの、startファイルが複数のファイルに分割されているもの。 ・初期のEPWING dataディレクトリーにhonmonファイルが存在しないもの。honmonファイルが 複数のファイルに分割されているもの。 ・EPWING V5 動作を確認していない。 bookinfoは以下のCD-ROMに対応していません。 ・初期の電子ブック 書籍ディレクトリーにstartファイルが存在しないもの。startファイルが複 数のファイルに分割されているもの。 ・初期のEPWING dataディレクトリーにhonmonファイルが存在しないもの。honmonファイルが 複数のファイルに分割されているもの。 ・EPWING V5 動作を確認していない。 squeezeは以下のCD-ROMに対応していません。 ・初期の電子ブック 書籍ディレクトリーにstartファイルが存在しないもの。startファイルが複 数のファイルに分割されているもの。 ・初期のEPWING dataディレクトリーにhonmonファイルが存在しないもの。honmonファイルが 複数のファイルに分割されているもの。 ・特殊な形式の書籍ファイル catdumpでInfoBlockの値が0001以外になっている書籍ファイル。squeezeが 認識しないインデックス構造やデータ表示制御記述子を含む書籍ファイル。 ・EPWING V4以降の圧縮書籍 dataディレクトリーにhonmon2ファイルの存在するもの。 ・EPWING V5 動作を確認していない。 5.2 動作確認済みCD-ROM 以下ではEPWUTILで動作確認済みのCD-ROMと、squeezeの標準オプションで各書籍 を圧縮したときのサイズを挙げておきます。 ・電子ブック版 Oxford Dictionary and Thesaurus(EBG) /oxford/start 55MB → 25MB (-g オプションを付けて実行) ・電子ブック版研究社新英和・和英中辞典(EBXA) /eiwa/start 63MB → 37MB /waei/start 17MB → 17MB ・電子ブック版研究社リーダーズ+プラス(EBXA) /plus/start 175MB → 155MB ・電子ブック版広辞苑第四版(EBXA) /koujien/start 167MB → 69MB ・研究社新英和・和英中辞典(EPWING 2.0) /chujiten/data/honmon 523MB → 119MB ・研究社リーダーズ+プラス(EPWING 1.0) /plus/data/honmon 450MB → 274MB ・広辞苑第四版(カラー)(EPWING 2.0) /koujien/data/honmon 434MB → 113MB ・大辞林(EPWING 1.0) /dgx01/data/honmon 324MB → 117MB ・スーパー大辞林(EPWING 2.0) /daijirin/data/honmon 640MB → 142MB ※ ・辞・典・盤97(EPWING 1.0) /iwakoku/data/honmon 23MB → 23MB /chujiten/data/honmon 84MB → 84MB /chiezo/data/honmon 20MB → 20MB /mypaedia/data/honmon 90MB → 84MB ・W辞ショック!(EPWING 1.0) /multi/data/honmon 290MB → 89MB ※ ・学研辞書(EPWING 1.0)(富士通のWindows PCに付属) /kokugo/data/honmon 13MB → 13MB /kanwa/data/honmon 25MB → 3MB ※ /eiwa/data/honmon 11MB → 11MB /waei/data/honmon 15MB → 15MB ※これらについては標準オプションは不適当であり、漢和辞典のための複合検 索インデックスが削除されている。 以下の製品については、処理できないことが判明しています。 ・三省堂マック辞典(EBXA)(Macintosh Performaに付属) 図版見出し(0D)の中に図版データ(D1)らしきものが混在している。図版見出 しを削除すれば処理可能かもしれない。 ・三省堂ワードハンター(EPWING 1.0) 処理は無事に終了するが、検索できない。ニューセンチュリー英和・新クラ ウン和英辞典とデイリーコンサイス英和・和英辞典に相互参照があるようで、 その仕様が不明のため対応できない。 ・NEC辞書ステーション(EPWING 1.0) 三省堂ワードハンターとほぼ同じ。 ・富士通スーパー統合辞書97(EPWING 4.0) ・富士通スーパー統合辞書98(EPWING 4.0) ・広辞苑第五版(EPWING 5.0) これらはEPWING V4以降の圧縮書籍であり、現在のところ圧縮フォーマット が不明であるため対応できない。 ---------------------------------------------------------------------------- 6. 利用条件 ---------------------------------------------------------------------------- このプログラムの利用・改変・再配布にはいかなる制限もありません。原作者は このプログラムに関するすべての著作権を放棄すること、またいかなる場合でも 著作者人格権を主張しないことを表明します。言い換えれば、原作者はこのプロ グラムがパブリックドメインに置かれたものとして扱われることを期待します。 オリジナル版・改変版の商業的利用あるいは各種メディアへの転載・収録などに ついても、原作者への連絡は一切不要です。 ただし、原作者はこのプログラムに関していかなる保証も行いません。原作者は このプログラムが期待された動作をすること、特定の目的に対して有用であるこ とを保証せず、またこのプログラムを利用したことによって生起したいかなる損 害に対する責任も負わないものとします。 ---------------------------------------------------------------------------- 7. 原作者 ---------------------------------------------------------------------------- 太田純 (Junn Ohta) Internet: ohta@src.ricoh.co.jp ← メールはこちらまで NIFTY: JCF00656 ---------------------------------------------------------------------------- 8. 履歴 ---------------------------------------------------------------------------- 2000/04/13 - バージョン1.1をリリース catdump 1.1 bookinfo 1.0 squeeze 1.1 o catdump と squeeze が -g オプションにより EBG に対応。 (Thanks to yamagata@nwgpc.kek.jp) 1999/01/12 - バージョン1.0をリリース catdump 1.0 bookinfo 1.0 squeeze 1.0 ============================================================================ epwutil-1.1.orig/makefile.dos0100644000175000017500000000067006646727127015632 0ustar mhattamhatta# EPWUTIL Makefile for Turbo C++ 1.0 CC = tcc CFLAGS = -O -G -DMSDOS -DSJIS .c.obj: $(CC) -c $(CFLAGS) $*.c all: catdump.exe bookinfo.exe squeeze.exe catdump.exe: catdump.obj $(CC) $(CFLAGS) -ecatdump.exe catdump.obj bookinfo.exe: bookinfo.obj bread.obj epw.h $(CC) $(CFLAGS) -ebookinfo.exe bookinfo.obj bread.obj squeeze.exe: squeeze.obj bread.obj bwrite.obj epw.h $(CC) $(CFLAGS) -esqueeze.exe squeeze.obj bread.obj bwrite.obj epwutil-1.1.orig/makefile.unx0100644000175000017500000000063206646727352015655 0ustar mhattamhatta# EPWUTIL Makefile for UNIX/gcc CC = gcc CFLAGS = -DUNIX -DEUC .c.o: $(CC) -c $(CFLAGS) $*.c all: catdump bookinfo squeeze catdump: catdump.o $(CC) $(CFLAGS) -o catdump catdump.o bookinfo: bookinfo.o bread.o epw.h $(CC) $(CFLAGS) -o bookinfo bookinfo.o bread.o squeeze: squeeze.o bread.o bwrite.o epw.h $(CC) $(CFLAGS) -o squeeze squeeze.o bread.o bwrite.o clean: -rm catdump bookinfo squeeze *.o epwutil-1.1.orig/squeeze.c0100644000175000017500000011001207075275432015155 0ustar mhattamhatta/* * squeeze - 電子ブック/EPWING 書籍軽量化 * * Written by Junn Ohta (ohta@src.ricoh.co.jp). Public Domain. * Modified by yamagata@nwgpc.kek.jp on 2000/04/13 */ char *progname = "squeeze"; char *version = "1.1"; char *date = "2000/04/13"; char *author = "Junn Ohta (ohta@src.ricoh.co.jp)"; #include #include #include #include #include #include #include #include "epw.h" /* * 書籍構成要素種別 */ #define T_UNKNOWN 0 /* 不明 */ #define T_TEXT 1 /* 本文、メニュー、見出し */ #define T_INDEX 2 /* インデックス */ #define T_DATA 3 /* 音声、図版、外字 */ #define T_CINFO 4 /* 複合検索管理情報 */ /* * インデックス種別 */ #define IT_UNKNOWN 0 /* 不明 */ #define IT_DIRECT 1 /* 見出しを経由せず直接本文へ */ #define IT_NORMAL 2 /* 見出し経由で本文へ */ #define IT_COND 3 /* 条件検索 */ #define IT_ITEM 4 /* 項目別条件検索 */ /* * 書籍構成要素属性表 */ typedef struct itype_t { byte idmin; byte idmax; int must; /* 新しい書籍にコピーするか? */ int type; int idxtype; } ITYPE_T; ITYPE_T itypetbl[] = { { 0x00, 0x00, TRUE, T_TEXT, 0 }, /* 本文 */ { 0x01, 0x01, TRUE, T_TEXT, 0 }, /* メニュー */ { 0x02, 0x02, TRUE, T_TEXT, 0 }, /* 著作権表示 */ { 0x03, 0x03, FALSE, T_TEXT, 0 }, /* 条件検索見出し */ { 0x04, 0x04, TRUE, T_TEXT, 0 }, /* 前方一致かな見出し */ { 0x05, 0x05, TRUE, T_TEXT, 0 }, /* 前方一致表記形見出し */ { 0x06, 0x06, TRUE, T_TEXT, 0 }, /* 後方一致かな見出し */ { 0x07, 0x07, TRUE, T_TEXT, 0 }, /* 後方一致表記形見出し */ { 0x08, 0x08, TRUE, T_TEXT, 0 }, /* 前方一致英字見出し */ { 0x09, 0x09, TRUE, T_TEXT, 0 }, /* 後方一致英字見出し */ { 0x0a, 0x0a, FALSE, T_TEXT, 0 }, /* クロス検索見出し */ { 0x0b, 0x0b, FALSE, T_TEXT, 0 }, /* 項目番号見出し */ { 0x0d, 0x0d, FALSE, T_TEXT, 0 }, /* 項目別条件検索見出し */ { 0x0f, 0x0f, FALSE, T_TEXT, 0 }, /* 図版見出し */ { 0x20, 0x20, FALSE, T_TEXT, 0 }, /* メニュー */ { 0x21, 0x21, FALSE, T_TEXT, 0 }, /* 著作権表示 */ { 0x23, 0x23, FALSE, T_TEXT, 0 }, /* 著作権表示(1行表示用) */ { 0x24, 0x24, FALSE, T_TEXT, 0 }, /* 音声見出し */ { 0x30, 0x30, FALSE, T_INDEX, IT_DIRECT }, /* かなINDEX */ { 0x40, 0x40, FALSE, T_INDEX, IT_DIRECT }, /* 英字INDEX */ { 0x50, 0x50, FALSE, T_INDEX, IT_DIRECT }, /* 漢字INDEX */ { 0x60, 0x60, FALSE, T_INDEX, IT_DIRECT }, /* 表記形INDEX */ { 0x70, 0x70, TRUE, T_INDEX, IT_NORMAL }, /* 後方一致かなINDEX */ { 0x71, 0x71, TRUE, T_INDEX, IT_NORMAL }, /* 後方一致表記形INDEX */ { 0x72, 0x72, TRUE, T_INDEX, IT_NORMAL }, /* 後方一致英字INDEX */ { 0x80, 0x80, FALSE, T_INDEX, IT_COND }, /* 条件検索INDEX */ { 0x81, 0x81, FALSE, T_INDEX, IT_COND }, /* クロス検索INDEX */ { 0x90, 0x90, TRUE, T_INDEX, IT_NORMAL }, /* 前方一致かなINDEX */ { 0x91, 0x91, TRUE, T_INDEX, IT_NORMAL }, /* 前方一致表記形INDEX */ { 0x92, 0x92, TRUE, T_INDEX, IT_NORMAL }, /* 前方一致英字INDEX */ { 0xa0, 0xa0, FALSE, T_INDEX, IT_ITEM }, /* 項目番号INDEX */ { 0xa1, 0xa1, FALSE, T_INDEX, IT_ITEM }, /* 項目別条件検索INDEX */ { 0xb0, 0xb0, FALSE, T_INDEX, IT_UNKNOWN }, /* ページ検索INDEX */ { 0xb1, 0xb1, FALSE, T_INDEX, IT_UNKNOWN }, /* 漢字INDEX */ { 0xd0, 0xd0, FALSE, T_DATA, 0 }, /* モノクロ図版 */ { 0xd1, 0xd1, FALSE, T_DATA, 0 }, /* 拡張モノクロ図版 */ { 0xd2, 0xd2, FALSE, T_DATA, 0 }, /* カラー図版 */ { 0xd8, 0xd8, FALSE, T_DATA, 0 }, /* PCM音声 */ { 0xe0, 0xe0, FALSE, T_DATA, 0 }, /* 色見本 */ { 0xf0, 0xf0, FALSE, T_DATA, 0 }, /* 暗証 */ { 0xf1, 0xf1, TRUE, T_DATA, 0 }, /* 外字(16×16ドット) */ { 0xf2, 0xf2, TRUE, T_DATA, 0 }, /* 外字(8×16ドット) */ { 0xf3, 0xf3, TRUE, T_DATA, 0 }, /* 外字(24×24ドット) */ { 0xf4, 0xf4, TRUE, T_DATA, 0 }, /* 外字(12×24ドット) */ { 0xf5, 0xf5, TRUE, T_DATA, 0 }, /* 外字(30×30ドット) */ { 0xf6, 0xf6, TRUE, T_DATA, 0 }, /* 外字(15×30ドット) */ { 0xf7, 0xf7, TRUE, T_DATA, 0 }, /* 外字(48×48ドット) */ { 0xf8, 0xf8, TRUE, T_DATA, 0 }, /* 外字(24×48ドット) */ { 0xff, 0xff, FALSE, T_CINFO, 0 }, /* 複合検索管理情報 */ { 0x00, 0x2f, FALSE, T_TEXT, 0 }, /* その他のテキストデータ */ { 0x70, 0x7f, FALSE, T_INDEX, IT_NORMAL }, /* その他の後方一致INDEX */ { 0x80, 0x8f, FALSE, T_INDEX, IT_COND }, /* その他の条件検索INDEX */ { 0x90, 0x9f, FALSE, T_INDEX, IT_NORMAL }, /* その他の前方一致INDEX */ { 0xa0, 0xbf, FALSE, T_INDEX, IT_UNKNOWN }, /* その他のINDEX */ { 0xd0, 0xdf, FALSE, T_DATA, 0 } /* マルチメディアデータ */ }; /* * 書籍構成要素再配置用のテーブル */ typedef struct slot_t { byte id; /* 構成要素識別子 */ dword topblk; /* 構成要素の先頭ブロック */ dword endblk; /* 構成要素の最終ブロック */ dword blks; /* 構成要素のブロック数 */ dword ntopblk; /* コピー先の先頭ブロック */ } SLOT_T; long blkno; uchr *bookfile; uchr *nbookfile; uchr *logfile; SLOT_T *slot; /* 再配置計算用テーブル */ int slots; /* 再配置計算用テーブルの要素数 */ long totalblks; byte buf[BLKSIZ]; byte tmpbuf[BLKSIZ]; int tty; int EBGmode = 0; int main(); void usage(); void init(); void term(); int squeeze(); int nonzero(); ulng val(); INFO_T *mknewinfo(); int checkslot(); long reloc(); int idmust(); int idtype(); int ididxtype(); int markdel(); int hex(); int copybook(); void putvoid(); int copytext(); int copyindex(); int copydata(); int main(ac, av) int ac; char **av; { int ret; ac--, av++; while (ac > 0 && **av == '-') { switch (av[0][1]) { case 'g': case 'G': EBGmode = 1; break; case 'd': case 'D': if (markdel(&av[0][2]) == ERR) usage(); break; default: usage(); } ac--, av++; } if (ac != 2) usage(); bookfile = av[0]; nbookfile = av[1]; init(); blkno = 1L; ret = squeeze(bookfile, blkno, nbookfile); term(); 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 [-g] [-d<削除IDリスト>]", progname); fprintf(stderr, " <入力書籍ファイル> <出力書籍ファイル>\n\n"); fprintf(stderr, "オプション:\n"); fprintf(stderr, " -g: EBG 専用モードにする\n"); fprintf(stderr, " -d: 指定IDの構成要素を取り除く\n"); exit(1); } void init() { time_t t; FILE *fp; tty = isatty(fileno(stderr)); logfile = (uchr *)malloc(strlen(progname) + strlen(".log") + 1); sprintf(logfile, "%s.log", progname); if ((fp = fopen(logfile, "a")) == NULL) return; time(&t); fprintf(fp, "処理開始: %s\n", ctime(&t)); fclose(fp); } void term() { time_t t; FILE *fp; if ((fp = fopen(logfile, "a")) == NULL) return; time(&t); fprintf(fp, "\n処理終了: %s\n", ctime(&t)); fclose(fp); } #ifdef VARARGS #include void log(va_alist) va_dcl #else #include void log(uchr *fmt, ...) #endif { FILE *fp; #ifdef VARARGS va_list va; uchr *fmt; va_start(va); fmt = va_arg(va, uchr *); #else va_list va; va_start(va, fmt); #endif vfprintf(stderr, fmt, va); if ((fp = fopen(logfile, "a")) != NULL) { vfprintf(fp, fmt, va); fclose(fp); } va_end(va); } int squeeze(bookfile, blkno, nbookfile) char *bookfile, *nbookfile; long blkno; { int i; INFO_T *infop, *ninfop; SLOT_T *slotp; if (open_book(bookfile) == ERR) { log("%s がオープンできません\n", bookfile); return ERR; } if ((infop = getinfo(blkno)) == NULL) { log("書籍管理情報が取得できません\n"); return ERR; } ninfop = mknewinfo(infop); if (ninfop == NULL) { log("メモリーが足りません\n"); return ERR; } log("入力ファイル = %s\n", bookfile); log("出力ファイル = %s\n\n", nbookfile); log("《再配置プラン》\n\n"); log("ID 開始ブロック 終了ブロック サイズ 再配置先\n"); slotp = slot; for (i = 0; i < slots; i++) { log("%02X %8lu %8lu %8lu %8lu\n", slotp->id, slotp->topblk, slotp->endblk, slotp->blks, slotp->ntopblk); slotp++; } log("\n"); if (checkslot() == ERR) { log("書籍ファイルの再構成を中止しました\n"); return ERR; } if (open_newbook(nbookfile) == ERR) { log("%s がオープンできません\n", nbookfile); return ERR; } if (putinfo(ninfop, 1L) == ERR) { log("書籍管理情報が書き込めません\n"); return ERR; } if (copybook() == ERR) { log("書籍ファイルの再構成を中止しました\n"); return ERR; } close_book(); if (close_newbook() == ERR) { log("書籍ファイルがクローズできません\n"); return ERR; } return OK; } 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; } INFO_T * mknewinfo(infop) INFO_T *infop; { int i, j, k, m, n; int items, cents, citems, cinfos; long topblk; INFO_T *ninfop; ITEM_T *itemp, *nitemp; CINFO_T *cinfop, *ncinfop; CENT_T *centp, *ncentp; CITEM_T *citemp, *ncitemp; /* * コピーする構成要素の数(items)と * 複合検索管理情報の数(cinfos)と * 再配置計算用テーブルの要素数(slots)を数える。 * 構成要素が複合検索管理情報(ID_CINFO)の場合、 * itemsには1、slotsには下位構成要素の総数が加算される。 * 複合検索の下位構成要素は重複することがあるが、 * ここでは重複してもかまわずカウントする。 */ items = 0; cinfos = 0; slots = 0; itemp = infop->item; for (i = 0; i < infop->items; i++) { if (!idmust(itemp->itemid)) { itemp++; continue; } if (itemp->itemid != ID_CINFO) { items++; slots++; itemp++; continue; } items++; cinfos++; cinfop = itemp->cinfo; centp = cinfop->cent; for (j = 0; j < cinfop->cents; j++) { citemp = centp->citem; for (k = 0; k < centp->citems; k++) { slots++; citemp++; } centp++; } itemp++; } /* * 構成要素情報をコピーし、複合検索管理情報を再配置する。 * 書籍管理情報は最初のブロックに書き込まれるので、 * 複合検索管理情報は2ブロックめ以降に再配置される。 */ ninfop = (INFO_T *)malloc(sizeof(INFO_T)); if (ninfop == NULL) return NULL; *ninfop = *infop; ninfop->items = items; nitemp = (ITEM_T *)malloc(sizeof(ITEM_T) * items); if (nitemp == NULL) return NULL; ninfop->item = nitemp; topblk = 2L; /* 複合検索管理情報の開始ブロック */ itemp = infop->item; nitemp = ninfop->item; for (i = 0; i < infop->items; i++) { if (!idmust(itemp->itemid)) { itemp++; continue; } *nitemp = *itemp; if (itemp->itemid != ID_CINFO) { /* * 複合検索管理情報以外の構成要素 */ itemp++; nitemp++; continue; } /* * 複合検索管理情報 */ nitemp->topblk = topblk++; cinfop = itemp->cinfo; ncinfop = (CINFO_T *)malloc(sizeof(CINFO_T)); if (ncinfop == NULL) return NULL; nitemp->cinfo = ncinfop; *ncinfop = *cinfop; centp = cinfop->cent; ncentp = (CENT_T *)malloc(sizeof(CENT_T) * ncinfop->cents); if (ncentp == NULL) return NULL; ncinfop->cent = ncentp; for (j = 0; j < cinfop->cents; j++) { *ncentp = *centp; citemp = centp->citem; ncitemp = (CITEM_T *)malloc(sizeof(CITEM_T) * ncentp->citems); if (ncitemp == NULL) return NULL; ncentp->citem = ncitemp; for (k = 0; k < centp->citems; k++) { *ncitemp = *citemp; citemp++; ncitemp++; } centp++; ncentp++; } itemp++; nitemp++; } /* * 再配置計算用テーブルを作ると同時に、 * 複合検索管理情報以外の構成要素も再配置する。 */ slot = (SLOT_T *)malloc(sizeof(SLOT_T) * slots); if (slot == NULL) return NULL; slots = 0; /* 重複を除いたslotsの個数を再計算する */ nitemp = ninfop->item; for (i = 0; i < ninfop->items; i++) { if (nitemp->itemid != ID_CINFO) { /* * 複合検索管理情報以外の構成要素 */ for (m = 0; m < slots; m++) { if (slot[m].topblk == nitemp->topblk) { nitemp->topblk = slot[m].ntopblk; break; } } if (m == slots) { slot[slots].id = nitemp->itemid; slot[slots].topblk = nitemp->topblk; slot[slots].endblk = nitemp->topblk + nitemp->blks - 1; slot[slots].blks = nitemp->blks; slot[slots].ntopblk = topblk; nitemp->topblk = topblk; topblk += nitemp->blks; slots++; } nitemp++; continue; } /* * 複合検索管理情報 */ ncinfop = nitemp->cinfo; ncentp = ncinfop->cent; for (j = 0; j < ncinfop->cents; j++) { ncitemp = ncentp->citem; for (k = 0; k < ncentp->citems; k++) { for (m = 0; m < slots; m++) { if (slot[m].topblk == ncitemp->ctopblk) { ncitemp->ctopblk = slot[m].ntopblk; break; } } if (m == slots) { slot[slots].id = ncitemp->citemid; slot[slots].topblk = ncitemp->ctopblk; slot[slots].endblk = ncitemp->ctopblk + ncitemp->cblks - 1; slot[slots].blks = ncitemp->cblks; slot[slots].ntopblk = topblk; ncitemp->ctopblk = topblk; topblk += ncitemp->cblks; slots++; } ncitemp++; } ncentp++; } nitemp++; } return ninfop; } int checkslot() { int i, err; err = 0; for (i = 0; i < slots; i++) { if (idtype(slot[i].id) == T_UNKNOWN) { log("構造が不明の書籍構成要素があります(ID=%02X)\n", slot[i].id); err++; } if (idtype(slot[i].id) == T_INDEX && ididxtype(slot[i].id) == IT_UNKNOWN) { log("構造が不明のインデックスがあります(ID=%02X)\n", slot[i].id); err++; } } if (err) return ERR; return OK; } long reloc(blk) long blk; { int i; SLOT_T *slotp; slotp = slot; for (i = 0; i < slots; i++) { if (blk >= slotp->topblk && blk <= slotp->endblk) return blk - slotp->topblk + slotp->ntopblk; slotp++; } return 0L; } 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 idtype(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].type; } return T_UNKNOWN; } int ididxtype(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].idxtype; } return IT_UNKNOWN; } 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; } 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; } int copybook() { int i, ret; SLOT_T *p; if (tty) { fprintf(stderr, "処理中です(0%%)"); fflush(stderr); } totalblks = slot[slots-1].ntopblk + slot[slots-1].blks - 1; p = slot; for (i = 0; i < slots; i++) { if (locate_block(p->topblk) == ERR) { if (tty) putc('\n', stderr); log("ファイルの読み込みに失敗しました\n"); return ERR; } if (locate_newblock(p->ntopblk) == ERR) { if (tty) putc('\n', stderr); log("ファイルの書き込みに失敗しました\n"); return ERR; } switch (idtype(p->id)) { case T_TEXT: ret = copytext(p->id, p->topblk, p->blks); break; case T_INDEX: ret = copyindex(p->id, p->topblk, p->blks, ididxtype(p->id)); break; case T_DATA: ret = copydata(p->id, p->topblk, p->blks); break; } if (ret == ERR) return ERR; p++; } if (tty) fprintf(stderr, "\r終了しました \n"); else log("終了しました\n"); return OK; } void putvoid(n) int n; { if (n >= 2) { /* * "→□"を書き込む */ if (!EBGmode) { putword(0x222a); putword(0x2222); } else { putbyte('-'); putbyte('>'); putbyte('['); putbyte(']'); } n -= 2; } if (n >= 3 && n & 1) { putword(0x1fe0); /* 拡張強調表示開始 */ putword(0x0001); putword(0x1fe1); /* 拡張強調表示終了 */ n -= 3; } while (n >= 2) { putword(0x1f04); /* 半角開始 */ putword(0x1f05); /* 半角終了 */ n -= 2; } while (n--) if (!EBGmode) { putword(0x2121); /* 空白 */ } else { putbyte(' '); /* 空白 */ putbyte(' '); /* 空白 */ } } int copytext(itemid, topblk, blks) int itemid; long topblk, blks; { int i, pc, npc, curoff, erroff; long err, rel, curblk, endblk, errblk; long blk1, blk2, off1, off2, bcd1, bcd2; word w, w1, w2; byte *p; #ifdef TEST long nerr = 0L; #endif if (tty) { pc = -1; putc('\r', stderr); } log("ID=%02X, 種別=テキスト, 開始ブロック=%ld, ブロック数=%ld\n", itemid, topblk, blks); err = 0L; rel = 0L; reset_error(); endblk = topblk + blks - 1; for (;;) { if (get_error() > 0) { if (tty) putc('\n', stderr); log("ファイルの書き込み中にエラーが発生しました\n"); return ERR; } curblk = cur_block(); curoff = cur_off(); if (curblk > endblk || curblk == endblk && curoff == BLKSIZ) break; if (tty) { npc = (int)(cur_newblock() * 100 / totalblks); if (npc > pc) { fprintf(stderr, "\r処理中です(%d%%)", npc); fflush(stderr); pc = npc; } } if (!EBGmode) { w = getword(); } else { w = getbyte(); } again: if (!EBGmode) { if (w >= 0x2121 && w <= 0x7e7e || w >= 0xa121 && w <= 0xfe7e) { /* * JIS文字。仕様上の文字範囲は以下の通りのはず。 * 通常文字: 2121〜7426 * 外字: a121〜fe7e * しかし三省堂ワードハンターの現代国語辞典に7671、 * 電子ブック版研究社新英和・和英中辞典に7440がある。 */ putword(w); w = getword(); goto again; } } else { if (w == 0) { } else if (w == 0x1f) { w = w << 8 | getbyte(); } else { putbyte(w & 0xff); if (0 < w && w < 0x1f) { /* EBG gaiji */ w = getbyte(); putbyte(w & 0xff); } w = getbyte(); goto again; } } if (w == 0x0000) { /* * パディング */ if (!EBGmode) { putword(w); } else { putbyte(w); } continue; } /* * 表示制御記述子 */ if ((w & 0xff00) == 0x1f00) { switch (w & 0x00ff) { case 0x09: /* 字下げ指定 */ case 0x1a: /* JIS X4081附属書の指示による */ case 0x1b: /* JIS X4081附属書の指示による */ case 0x1c: /* JIS X4081附属書の指示による */ case 0x1d: /* JIS X4081附属書の指示による */ case 0x1e: /* JIS X4081附属書の指示による */ case 0x1f: /* JIS X4081附属書の指示による */ case 0x41: /* 検索キー記述子 */ case 0x45: /* 図版データ群識別子 (DIC 0.23による) */ case 0xe0: /* 拡張強調表示開始指定 */ case 0xe2: /* 保護開始指定 (DIC 0.23による) */ /* * 直後の1WORDをそのままコピーする。 * 1f45は電子ブック版広辞苑第四版に出てくる。 */ putword(w); w1 = getword(); putword(w1); break; case 0x31: /* 図版見出し中の指示開始? */ case 0x32: /* 電子ブック拡張モノクロ図版 */ case 0x42: /* 別項目参照記述子 */ case 0x44: /* 図版データ識別子 (DIC 0.23による) */ case 0x46: /* 図版メニュー識別子 (DIC 0.23による) */ case 0x49: /* 未確認: 表? (cdrom2による) */ case 0x4b: /* 未確認: 図形枠? (cdrom2による) */ case 0x4c: /* 未確認: 図形枠? (cdrom2による) */ case 0x4e: /* 未確認: ポインタ? (cdrom2による) */ case 0x4f: /* 未確認: ポインタ? (cdrom2による) */ /* * 終了識別子までを一時的に保存しておき、 * 終了識別子の直後にあるBCD4+BCD2を見て、 * 参照先がなければ全体を「→□」で置き換える。 * * 電子ブック版研究社新英和・和英中辞典では * 1f42の終了識別子1f62でオフセットが * 2048以上になっている箇所がある。 * データを見るとオフセットから2048を引いて * 次のブロックを参照するという方法で * つじつまがあっているようだ。 */ p = tmpbuf; *p++ = w >> 8; *p++ = w & 0xff; w1 = w + 0x0020; if (!EBGmode) { while ((w = getword()) != w1) { *p++ = w >> 8; *p++ = w & 0xff; } } else { int ww; while (1) { w = getbyte(); if (w == 0x1f) { ww = getbyte(); if (w << 8 | ww == w1) { w = w1; break; } else { *p++ = w; *p++ = ww; } } else { *p++ = w; } } } blk1 = getbcd(4); off1 = getbcd(2); if (blk1 < 0 || off1 < 0 || off1 >= BLKSIZ) { err++; errblk = cur_block(); erroff = cur_off(); #ifdef TEST if (tty) putc('\r', stderr); log("err: pos=%lu:%d\n", cur_block(), cur_off()); #endif } blk1 = reloc(blk1); if (blk1 == 0L) { putvoid((p - tmpbuf) / 2 + 4); } else { putbytes(tmpbuf, p - tmpbuf); putword(w); putbcd(blk1, 4); putbcd(off1, 2); rel++; } break; case 0x33: /* 電子ブック音声 (ndtpdによる) */ /* * ハードディスク上では再生不能なので * 全体を「→□」で置き換える。 */ i = 1; while ((w = getword()) != 0x1f53) i++; i++; w = getword(); /* * 電子ブック版広辞苑第四版の図版見出しを見る限り、 * ここに来るのはBCD4+BCD2ではないようだ。 */ bcd1 = getbcd(3); bcd2 = getbcd(3); if (bcd1 < 0 || bcd2 < 0) { err++; errblk = cur_block(); erroff = cur_off(); #ifdef TEST if (tty) putc('\r', stderr); log("err: pos=%lu:%d\n", cur_block(), cur_off()); #endif } i += 4; putvoid(i); break; case 0x48: /* 音声データ識別子 (DIC 0.23による) */ /* * 1f48直後の5WORDはCDトラックを参照している。 * ハードディスク上では再生不能なので * 1f68までの全体を「→□」で置き換える。 * 1f68の後にはポインターは来ない。 * 1f48を使っている例はEPWING版大辞林にある。 */ i = 1; while ((w = getword()) != 0x1f68) i++; i++; putvoid(i); break; case 0x4a: /* EPWING PCM音声 */ /* * 1f4a+WORD+WORD+BCD4+BCD2+BCD4+BCD2+〜+1f6a * という構造をしている。 */ w1 = getword(); w2 = getword(); blk1 = getbcd(4); off1 = getbcd(2); blk2 = getbcd(4); off2 = getbcd(2); if (blk1 < 0 || off1 < 0 || off1 >= BLKSIZ || blk2 < 0 || off2 < 0 || off2 >= BLKSIZ) { err++; errblk = cur_block(); erroff = cur_off(); #ifdef TEST if (tty) putc('\r', stderr); log("err: pos=%lu:%d\n", cur_block(), cur_off()); #endif } blk1 = reloc(blk1); blk2 = reloc(blk2); if (blk1 == 0L || blk2 == 0L) { i = 9; while (getword() != 0x1f6a) i++; i++; putvoid(i); } else { putword(w); putword(w1); putword(w2); putbcd(blk1, 4); putbcd(off1, 2); putbcd(blk2, 4); putbcd(off2, 2); rel++; rel++; while ((w = getword()) != 0x1f6a) putword(w); putword(0x1f6a); } break; case 0x4d: /* カラー図版 */ /* * ここは非常にあやしい。実例はいまのところ * EPWING版広辞苑第四版の本文にしか見かけない。 * 例としては「アイガー」で2枚のカラー図版を * 参照しているところがある。すべての箇所が * 1f4d+0009+0000*5+BCD4+BCD2+ラベル+1f6d * という形であり、それ以外の組み合わせはない。 * とりあえず * 1f4d+WORD*6+BCD4+BCD2+ラベル+1f6d * という形式であると解釈しておく。 */ p = tmpbuf; *p++ = w >> 8; *p++ = w & 0xff; for (i = 0; i < 6; i++) { w = getword(); *p++ = w >> 8; *p++ = w & 0xff; } blk1 = getbcd(4); off1 = getbcd(2); if (blk1 < 0 || off1 < 0 || off1 >= BLKSIZ) { err++; errblk = cur_block(); erroff = cur_off(); #ifdef TEST if (tty) putc('\r', stderr); log("err: pos=%lu:%d\n", cur_block(), cur_off()); #endif } blk1 = reloc(blk1); if (blk1 == 0L) { i = 1 + 6 + 3; while (getword() != 0x1f6d) i++; i++; putvoid(i); } else { putbytes(tmpbuf, p - tmpbuf); putbcd(blk1, 4); putbcd(off1, 2); rel++; while ((w = getword()) != 0x1f6d) putword(w); putword(0x1f6d); } break; case 0x62: /* 別項目参照終了記述子 */ case 0x63: /* メニュー終了記述子 */ /* * アスキー辞・典・盤97のマイペディア97で、 * 「日本」の別項目参照中、「→ポツダム宣言」 * の直後に「ヌ→二・一スト」という項目がある。 * どうやら1f42が254cに化けているようだ。 * case 0x42で1f62まで読んで処理しているのに * case 0x62があるのは、これに対応するため。 * (しかしデータ化けを訂正するわけではない。) */ putword(w); blk1 = getbcd(4); off1 = getbcd(2); if (blk1 < 0 || off1 < 0 || off1 >= BLKSIZ) { err++; errblk = cur_block(); erroff = cur_off(); #ifdef TEST if (tty) putc('\r', stderr); log("err: pos=%lu:%d\n", cur_block(), cur_off()); #endif } blk1 = reloc(blk1); putbcd(blk1, 4); putbcd(off1, 2); rel++; break; case 0x14: /* 色指定開始指定 (DIC 0.23による) */ case 0x67: /* 色見本メニュー終了識別子 (DIC 0.23による) */ do { putword(w); w = getword(); } while ((w & 0xff00) == 0x1e00); goto again; case 0x15: /* 色指定終了指定 (DIC 0.23による) */ /* * EPWNIG版広辞苑第四版CD-ROM(カラー)版の * 条件検索で「あんりょくしょく」を検索すると * 「オリーブ色」の見出し末尾の「】」の後で、 * 1f15の直後にどういうわけか0260が出てくる。 * ことといVer.2、富士通CD辞書検索V1.3L12、 * OASYS-CDView/Win V3.0L10では表示が化けないが、 * DDwin、ViewIng95、WordEngine2では化ける。 * 広辞苑のバグか? */ putword(w); w = getword(); if ((w & 0xff00) == 0x1f00) goto again; putword(w); break; default: putword(w); break; } continue; } /* * 電子ブック版三省堂マック辞典の英和・和英辞典 * 「センチュリ+ビジネス+クラウン」では書籍構成要素 * 0F(図版一覧)の中にD1(拡張モノクロ図版)のデータも * ごちゃまぜで入っているようだ。たいていのデータは * エラーとしてここに落ちてくるが、データの一部が * 表示制御記述子とたまたま一致してしまうと、開始・ * 終了記述子の対応がとれずにプログラムが異常終了 * してしまう可能性がある。うまい対策がないので、 * ここでは放置しておく。 */ putword(w); #ifdef TEST if (nerr++ < 20L) { if (tty) putc('\r', stderr); log("ERR: word=%04X, pos=%lu:%d(%04x)\n", w, curblk, curoff, curoff); } #endif err++; errblk = cur_block(); erroff = cur_off(); } if (err) { if (tty) putc('\n', stderr); log("未知の表示制御構造がありました(個数=%ld, 最終位置=%lu:%d)\n", err, errblk, erroff); } return OK; } int copyindex(itemid, topblk, blks, idxtype) int itemid; long topblk, blks; int idxtype; { int i, pc, npc, id, eid; int off1, off2, erroff; long n, err, ref, rel, errblk; long blk1, blk2; word len, cnt, num, dum; if (tty) { pc = -1; putc('\r', stderr); } log("ID=%02X, 種別=インデックス, 開始ブロック=%ld, ブロック数=%ld\n", itemid, topblk, blks); err = 0L; ref = 0L; rel = 0L; reset_error(); n = cur_newblock(); while (blks--) { if (tty) { npc = (int)(n++ * 100 / totalblks); if (npc > pc) { fprintf(stderr, "\r処理中です(%d%%)", npc); fflush(stderr); pc = npc; } } id = getbyte(); len = getbyte(); cnt = getword(); putbyte(id); putbyte(len); putword(cnt); if ((id & 0x80) == 0x00) { /* * 上位インデックスブロック */ for (i = 0; i < cnt; i++) { getbytes(buf, len); blk1 = getdword(); blk1 = reloc(blk1); if (blk1 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbytes(buf, len); putdword(blk1); rel++; } goto nextblock; } /* * 最下位インデックスブロック */ if ((id & 0x10) == 0x00) { /* * 一般型エントリ */ switch (idxtype) { case IT_DIRECT: for (i = 0; i < cnt; i++) { len = getbyte(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); if (off1 >= BLKSIZ) err++; blk1 = reloc(blk1); if (blk1 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putbytes(buf, len); putdword(blk1); putword(off1); rel++; } break; default: for (i = 0; i < cnt; i++) { len = getbyte(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); blk2 = getdword(); off2 = getword(); if (off1 > BLKSIZ || off2 >= BLKSIZ) { /* * 電子ブック版研究社新英和・和英中辞典では * オフセットoff1が2048になっている箇所がある。 * 次のブロックの先頭を参照すると解釈すれば * つじつまがあっているので、エラーにはしない。 * これに対応するため、ここだけエラーの範囲を * 「>= BLKSIZ」ではなく「> BLKSIZ」とする。 */ err++; } blk1 = reloc(blk1); blk2 = reloc(blk2); if (blk1 == 0L || blk2 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putbytes(buf, len); putdword(blk1); putword(off1); putdword(blk2); putword(off2); rel++; rel++; } break; } goto nextblock; } /* * 集団概念付きエントリ */ switch (idxtype) { case IT_DIRECT: for (i = 0; i < cnt; i++) { eid = getbyte(); putbyte(eid); if (eid == 0x00) { /* * 基本エントリ */ len = getbyte(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); if (off1 >= BLKSIZ) err++; blk1 = reloc(blk1); if (blk1 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putbytes(buf, len); putdword(blk1); putword(off1); rel++; } else if (eid == 0x80) { /* * 集団エントリ */ len = getbyte(); num = getword(); getbytes(buf, len); putbyte(len); putword(num); putbytes(buf, len); } else if (eid == 0xc0) { /* * メンバ情報 */ len = getbyte(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); if (off1 >= BLKSIZ) err++; blk1 = reloc(blk1); if (blk1 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putbytes(buf, len); putdword(blk1); putword(off1); rel++; } else { err++; break; } } break; case IT_NORMAL: for (i = 0; i < cnt; i++) { eid = getbyte(); putbyte(eid); if (eid == 0x00) { /* * 基本エントリ */ len = getbyte(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); blk2 = getdword(); off2 = getword(); if (off1 >= BLKSIZ || off2 >= BLKSIZ) err++; blk1 = reloc(blk1); blk2 = reloc(blk2); if (blk1 == 0L || blk2 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putbytes(buf, len); putdword(blk1); putword(off1); putdword(blk2); putword(off2); rel++; } else if (eid == 0x80) { /* * 集団エントリ */ len = getbyte(); num = getword(); getbytes(buf, len); putbyte(len); putword(num); putbytes(buf, len); } else if (eid == 0xc0) { /* * メンバ情報 */ len = getbyte(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); blk2 = getdword(); off2 = getword(); if (off1 >= BLKSIZ || off2 >= BLKSIZ) err++; blk1 = reloc(blk1); blk2 = reloc(blk2); if (blk1 == 0L || blk2 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putbytes(buf, len); putdword(blk1); putword(off1); putdword(blk2); putword(off2); rel++; } else { err++; break; } } break; case IT_COND: for (i = 0; i < cnt; i++) { eid = getbyte(); putbyte(eid); if (eid == 0x00) { /* * 基本エントリ */ len = getbyte(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); blk2 = getdword(); off2 = getword(); if (off1 >= BLKSIZ || off2 >= BLKSIZ) err++; blk1 = reloc(blk1); blk2 = reloc(blk2); if (blk1 == 0L || blk2 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putbytes(buf, len); putdword(blk1); putword(off1); putdword(blk2); putword(off2); rel++; } else if (eid == 0x80) { /* * 集団エントリ */ len = getbyte(); dum = getword(); num = getword(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); if (off1 >= BLKSIZ) err++; blk1 = reloc(blk1); if (blk1 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putword(dum); putword(num); putbytes(buf, len); putdword(blk1); putword(off1); rel++; } else if (eid == 0xc0) { /* * メンバ情報 */ blk1 = getdword(); off1 = getword(); if (off1 >= BLKSIZ) err++; blk1 = reloc(blk1); if (blk1 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putdword(blk1); putword(off1); rel++; } else { err++; break; } } break; case IT_ITEM: for (i = 0; i < cnt; i++) { eid = getbyte(); putbyte(eid); if (eid == 0x00) { /* * 基本エントリ */ len = getbyte(); getbytes(buf, len); blk1 = getdword(); off1 = getword(); blk2 = getdword(); off2 = getword(); if (off1 >= BLKSIZ || off2 >= BLKSIZ) err++; blk1 = reloc(blk1); blk2 = reloc(blk2); if (blk1 == 0L || blk2 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putbyte(len); putbytes(buf, len); putdword(blk1); putword(off1); putdword(blk2); putword(off2); rel++; } else if (eid == 0x80) { /* * 集団エントリ */ len = getbyte(); dum = getword(); num = getword(); getbytes(buf, len); putbyte(len); putword(dum); putword(num); putbytes(buf, len); } else if (eid == 0xc0) { /* * メンバ情報 */ blk1 = getdword(); off1 = getword(); blk2 = getdword(); off2 = getword(); if (off1 >= BLKSIZ || off2 >= BLKSIZ) err++; blk1 = reloc(blk1); blk2 = reloc(blk2); if (blk1 == 0L || blk2 == 0L) { errblk = cur_block(); erroff = cur_off(); ref++; } putdword(blk1); putword(off1); putdword(blk2); putword(off2); rel++; } else { err++; break; } } break; } nextblock: if (err) { if (tty) putc('\n', stderr); log("インデックス構造に不整合があります(ブロック=%lu)\n", cur_block()); return ERR; } if (get_error() > 0 || write_newblock() == ERR) { if (tty) putc('\n', stderr); log("ファイルの書き込み中にエラーが発生しました\n"); return ERR; } read_block(); } if (ref > 0) { if (tty) putc('\n', stderr); log("参照先のないインデックスがあります(個数=%ld, 最終位置=%lu:%d)\n", ref, errblk, erroff); } return OK; } int copydata(itemid, topblk, blks) int itemid; long topblk, blks; { int pc, npc; long n; if (tty) { pc = -1; putc('\r', stderr); } log("ID=%02X, 種別=データ, 開始ブロック=%ld, ブロック数=%ld\n", itemid, topblk, blks); reset_error(); n = cur_newblock(); while (blks--) { if (tty) { npc = (int)(n++ * 100 / totalblks); if (npc > pc) { fprintf(stderr, "\r処理中です(%d%%)", npc); fflush(stderr); pc = npc; } } getbytes(buf, BLKSIZ); putbytes(buf, BLKSIZ); if (get_error() > 0) { if (tty) putc('\n', stderr); log("ファイルの書き込み中にエラーが発生しました\n"); return ERR; } } return OK; } epwutil-1.1.orig/squeeze.man0100644000175000017500000001545607074542675015533 0ustar mhattamhatta名称 squeeze - 電子ブック/EPWINGの書籍を軽量化する バージョン 1.1 - 2000/04/11 形式 squeeze [-g] [-d<削除IDリスト>] <入力書籍ファイル> <出力書籍ファイル> オプション -g: EBG 専用モードで起動する。 -d<削除IDリスト> <削除IDリスト>に並べた書籍構成要素を削除する <入力書籍ファイル> 入力元の書籍ファイル <出力書籍ファイル> 出力先の書籍ファイル 使用例 Dドライブの電子ブック版広辞苑本体を軽量化してc:\dic\koujien\startに 出力する(MS-DOS) C> squeeze d:\koujien\start c:\dic\koujien\start DドライブのEPWING広辞苑本体を軽量化してc:\dic\koujien\data\honmonに 出力する(MS-DOS) C> squeeze d:\koujien\data\honmon c:\dic\koujien\data\honmon 上記の例で図版・音声などのマルチメディアデータのみを削除する C> squeeze -dd0-fe d:\koujien\data\honmon c:\dic\koujien\data\honmon 説明 電子ブックやEPWINGの検索対象となる書籍ファイル(ファイル名は電子ブッ クではstart、EPWINGではhonmonなど)には、本文やメニュー、著作権表示、 インデックス情報、図版、音声など、さまざまな構成要素が含まれている。 squeezeは入力に指定された書籍を読み込み、特定の構成要素を削除し、残 りの構成要素をすき間なく並べ直して出力する。 squeezeを使うと、書籍ファイルから自分が利用しないインデックスやマル チメディアデータを取り除き、辞書を小さくすることができる。squeezeは EBXAのロゴのある電子ブック(1994年以降のもの)とEPWINGの非圧縮書籍に対 応している。 本文やメニューからの参照先(図版や音声など)が削除された場合、本文内の 参照指示は「→□」で置き換えられる。 squeezeでEPWING版広辞苑第四版を処理中の画面を以下に示す。 C> squeeze d:\koujien\data\honmon c:\dic\koujien\data\honmon 入力ファイル = d:\koujien\data\honmon 出力ファイル = c:\dic\koujien\data\honmon 《再配置プラン》 ID 開始ブロック 終了ブロック サイズ 再配置先 00 2 17738 17737 2 90 24468 28443 3976 17739 04 28444 32019 3576 21715 91 32020 37033 5014 25291 05 37034 44360 7327 30305 70 44361 48336 3976 37632 06 48337 51912 3576 41608 71 51913 56926 5014 45184 07 56927 64253 7327 50198 01 130499 130648 150 57525 02 216647 216647 1 57675 ID=00, 種別=テキスト, 開始ブロック=2, ブロック数=17737 ID=90, 種別=インデックス, 開始ブロック=24468, ブロック数=3976 ID=04, 種別=テキスト, 開始ブロック=28444, ブロック数=3576 ID=91, 種別=インデックス, 開始ブロック=32020, ブロック数=5014 処理中です(48%) 画面には、入出力ファイル名のあとに再配置プランが表示される。ここには 削除されずに出力される書籍構成要素のIDと、入力書籍ファイル中の開始・ 終了ブロック位置および占有ブロック数、さらに出力書籍ファイルに再配置 されたときの開始ブロック位置が示されている。書籍構成要素の詳細につい てはbookinfoのマニュアルbookinfo.manを参照されたい。 その後、処理の進行に応じて処理中の書籍構成要素に関する情報が表示され る。「処理中です」というメッセージとともにパーセンテージが示されるが、 これは出力全体の何パーセントを処理したかを示す数値だ。なお、画面に表 示されるのと同じ内容が、カレントディレクトリーのファイルsqueeze.log にも記録される。 どの書籍構成要素を削除するかは-dオプションで指定できる。-dの後には空 白をあけずに削除する構成要素のIDをカンマで区切って並べる。「-」を使 ってIDの範囲を指定することもできる。省略時の動作は本文、メニュー、著 作権表示、各種前方一致/後方一致インデックスと見出しを残すというもの で、次の-dオプションと等しい。 -d03,0a-6f,73-8f,93-ef,f9-ff この選択は一般的な国語辞典や英和・和英辞典に対しては有効だが、漢和辞 典には適当ではない。漢和辞典では複合検索を使って検索するものが多く、 その場合には削除する構成要素を個別に判断する必要がある。 EPWINGの国語辞典には、漢字かな交じり文字列で検索するための表記形イン デックスと見出しが含まれていることが多い。ひらがなの読みで検索するだ けなら、これらのインデックスと見出しは削除できる。その場合の指定は次 のようになる。(この場合は電子ブック外字も考慮しなくてよい。) -d03,05,07,0a-6f,71,73-8f,91,93-ff 英語辞典では、後方一致検索の必要性が比較的少ない。前方一致検索だけで よければ、後方一致検索のインデックスと見出しも削除できる。その場合の 指定は次のようになる。 -d03,06,09-8f,93-ef,f9-ff -dオプションの指定方法はbookinfoと共通であり、ある-dオプションを指定 したときのsqueezeの出力結果のサイズは、同じ-dオプションでbookinfoを 実行することによって予測できる。 なお、同じIDの要素を取捨選択して指定することはできない。たとえば、あ る複合検索だけを残して他の複合検索を削除するということはできない。ま た、複合検索指定(IDがFFのもの)を削除すると、その複合検索にかかわるす べての副構成要素も同時に削除される。 squeezeは電子ブックやEPWINGの書籍管理情報を参照し、必要な書籍構成要 素だけを残したうえで、それらが出力ファイルに詰めて並べられるようにイ ンデックスや本文テキスト内の参照アドレスを変換する。書籍の構造は完全 に公開されているわけではなく、いくつかの部分は推測に頼っている。した がって、対応が確認されていない書籍については処理できないかもしれない。 また、構造が不明の書籍もあり、その場合は処理に失敗する。具体的な対応 状況についてはepwutil.docの「5.制約事項」の項を参照されたい。 エラーメッセージ <入力書籍ファイル> がオープンできません 入力書籍ファイルとして指定したファイルが存在しない。 書籍管理情報が取得できません 入力書籍ファイルとして正しい書籍ファイルを指定していない。あるい はこの書籍ファイルでは書籍管理情報が先頭ブロックに存在しない。あ るいはEPWING V4以降の圧縮書籍を指定した。 メモリーが足りません 処理に必要なメモリーを割り当てることができなかった。他のプログラ ムを終了させてから再実行する。 <出力書籍ファイル> がオープンできません 出力書籍ファイルとして指定したファイルがすでに存在し、上書きでき ないモードになっている。あるいはパス指定の途中にあるディレクトリ ーが存在しない。あるいはディスクが一杯になっている。 書籍管理情報が書き込めません 書籍ファイルがクローズできません ファイルの書き込み中にエラーが発生しました ファイルの書き込みに失敗しました ディスクが一杯になっている。 構造が不明の書籍構成要素があります(ID=<構成要素種別>) 構造が不明のインデックスがあります(ID=<構成要素種別>) squeezeが対応していない書籍構成要素があった。この書籍構成要素を 残したままではsqueezeは処理が行えない。 未知の表示制御構造がありました(個数=<個数>, 最終位置=<位置>) 本文データにsqueezeが知らない表示制御構造があった。出力書籍ファ イルは作られているが、該当する表示制御構造を含む項目については正 しく複製されていない可能性がある。 インデックス構造に不整合があります(ブロック=<ブロック番号>) インデックス構造がsqueezeの想定する仕様に適合していない。この書 籍構成要素を残したままではsqueezeは処理が行えない。 参照先のないインデックスがあります(個数=<個数>, 最終位置=<位置>) インデックスから参照される見出しあるいは本文データが存在しない。 インデックスだけを残し、対応する見出しあるいは本文データを削除し ようとしている可能性がある。