/* * 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; }