/* * ebd2html - EBDumpの出力からEBStudioへの入力HTMLファイルを再構成する試み * Written by Junn Ohta (ohta@sdg.mdd.ricoh.co.jp), Public Domain. */ char *progname = "ebd2html"; char *version = "experimental-0.05"; char *date = "2005/01/03"; #include #include #include #include #include #include #include #include #include #include #include typedef unsigned char byte; typedef unsigned int word; typedef unsigned long dword; #ifndef O_BINARY #define O_BINARY 0 #endif #define OK 0 #define ERR (-1) #define TRUE 1 #define FALSE 0 /* -------------------- ユーティリティー関数 -------------------- */ #define LOG_FILE "ebd2html.log" /* ログファイル */ #define MAX_WORD 256 /* 単語の最大長 */ /* * 2バイト記号→1バイト記号変換表(0x8140〜0x8197) */ int zen2han[] = { ' ', ERR, ERR, ',', '.', ERR, ':', ';', '?', '!', ERR, ERR, ERR, ERR, ERR, '^', '~', '_', ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, '/','\\', '~', '|', '|', ERR, ERR,'\'','\'', '"', '"', '(', ')', '[', ']', '[', ']', '{', '}', ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, '+', '-', ERR, ERR, ERR, ERR, '=', ERR, '<', '>', ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR,'\\', '$', ERR, ERR, '%', '#', '&', '*', '@' }; int hexval(byte *); byte *skipsp(byte *); byte *skipch(byte *, int); byte *skipstr(byte *, byte *); byte *endstr(byte *); byte *addstr(byte *, byte *); int tohan(byte *); byte *getuptos(byte *, byte *, byte *); byte *getupto(byte *, byte *, byte); int iskanastr(byte *); void write_log(char *, ...); void message(char *, ...); /* * 2桁の16進数が示す値を返す */ int hexval(byte *p) { int i, n; n = 0; for (i = 0; i < 2; i++) { n <<= 4; if (*p >= '0' && *p <= '9') n += *p - '0'; else if (*p >= 'a' && *p <= 'f') n += *p - 'a' + 10; else if (*p >= 'A' && *p <= 'F') n += *p - 'A' + 10; else n = 0; p++; } return n; } /* * 空白を読み飛ばし、次の位置を返す */ byte * skipsp(byte *str) { while (*str == ' ' || *str == '\t') str++; return str; } /* * 指定文字まで読み飛ばし、その次の位置を返す */ byte * skipch(byte *str, int ch) { while (*str && *str != ch) { if (*str & 0x80) str++; str++; } if (*str == ch) str++; return str; } /* * 指定文字列まで読み飛ばし、その次の位置を返す * (文字列がなければ末尾の位置を返す) */ byte * skipstr(byte *str, byte *key) { byte *p; p = strstr(str, key); if (p) return p + strlen(key); return endstr(str); } /* * 文字列の末尾の位置を返す */ byte * endstr(byte *str) { while (*str) str++; return str; } /* * バッファに文字列を追加し、その末尾を返す(NULで終了はしない) */ byte * addstr(byte *dst, byte *str) { while (*str) *dst++ = *str++; return dst; } /* * 2バイト英数字を1バイト英数字に変換する */ int tohan(byte *str) { int high, low; high = str[0]; low = str[1]; if (high == 0x82) { if (low >= 0x4f && low <= 0x58) return '0' + low - 0x4f; if (low >= 0x60 && low <= 0x79) return 'A' + low - 0x60; if (low >= 0x81 && low <= 0x9a) return 'a' + low - 0x81; return ERR; } if (high == 0x81) { if (low >= 0x40 && low <= 0x97) return zen2han[low - 0x40]; return ERR; } return ERR; } /* * 区切り文字セットまでの単語を切り出し、区切り文字の位置を返す */ byte * getuptos(byte *buf, byte *word, byte *stops) { byte *p, *q; p = buf; q = word; while (*p && *p != '\r' && *p != '\n') { if (strchr(stops, *p)) break; if (*p & 0x80) *q++ = *p++; *q++ = *p++; } *q = '\0'; return p; } /* * 区切り文字までの単語を切り出し、区切り文字の位置を返す */ byte * getupto(byte *buf, byte *word, byte stop) { byte *p, *q; p = buf; q = word; while (*p && *p != stop && *p != '\r' && *p != '\n') { if (*p & 0x80) *q++ = *p++; *q++ = *p++; } *q = '\0'; return p; } /* * 文字列がひらがな/カタカナ/長音のみで構成されているか? */ int iskanastr(byte *str) { while (*str) { if (str[0] == 0x81 && str[1] == 0x5b || str[0] == 0x82 && str[1] >= 0x9f || str[0] == 0x83 && str[1] <= 0x96) { str += 2; continue; } return FALSE; } return TRUE; } /* * メッセージをログファイルに書く */ void write_log(char *fmt, ...) { char buf[BUFSIZ]; FILE *fp; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); if ((fp = fopen(LOG_FILE, "a")) == NULL) return; fputs(buf, fp); fclose(fp); } /* * メッセージを表示し、ログファイルにも書く */ void message(char *fmt, ...) { char buf[BUFSIZ]; FILE *fp; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); fputs(buf, stdout); fflush(stdout); if ((fp = fopen(LOG_FILE, "a")) == NULL) return; fputs(buf, fp); fclose(fp); } /* -------------------- メイン -------------------- */ #define MAX_PATH 1024 /* パス名の最大長 */ #define MAX_DLINE 1024 /* データファイルの最大行長 */ #define MAX_HLINE 256 /* HTMLファイルのおよその最大長 */ #define MAX_BUFF 65535 /* 本文データ行の最大長(64KB) */ #define FKINDEX_FILE "fkindex.txt" /* かなインデックスダンプデータ */ #define FKINDEX_WORK "fkindex.tmp" /* かなインデックス一時ファイル */ #define FKINDEX_DATA "fkindex.dat" /* ソート済みかなインデックス */ #define FKTITLE_FILE "fktitle.txt" /* かな見出しダンプデータ */ #define FKTITLE_DATA "fktitle.dat" /* かな見出し作業バイナリデータ */ #define FHINDEX_FILE "fhindex.txt" /* 表記インデックスダンプデータ */ #define FHINDEX_WORK "fhindex.tmp" /* 表記インデックス一時ファイル */ #define FHINDEX_DATA "fhindex.dat" /* ソート済み表記インデックス */ #define FHTITLE_FILE "fhtitle.txt" /* 表記見出しダンプデータ */ #define FHTITLE_DATA "fhtitle.dat" /* 表記見出し作業バイナリデータ */ #define FAINDEX_FILE "faindex.txt" /* 英字インデックスダンプデータ */ #define FAINDEX_WORK "faindex.tmp" /* 英字インデックス一時ファイル */ #define FAINDEX_DATA "faindex.dat" /* ソート済み英字インデックス */ #define FATITLE_FILE "fatitle.txt" /* 英字見出しダンプデータ */ #define FATITLE_DATA "fatitle.dat" /* 英字見出し作業バイナリデータ */ #define ZGAIJI_FILE "zgaiji.txt" /* 全角16ドット外字ダンプデータ */ #define HGAIJI_FILE "hgaiji.txt" /* 半角16ドット外字ダンプデータ */ #define GFONT_FILE "Gaiji.xml" /* EBStudio用外字マップファイル */ #define GMAP_FILE "GaijiMap.xml" /* EBStudio用外字フォント */ #define HONMON_FILE "honmon.txt" /* 本文ダンプデータ */ #define INI_FILE "ebd2html.ini" /* ebd2html設定ファイル */ typedef struct index_t { /* インデックス/見出しデータ */ dword dblk; /* 本文ブロック番号 */ word dpos; /* 本文ブロック内位置 */ dword tblk; /* 見出しブロック番号 */ word tpos; /* 見出しブロック内位置 */ byte str[MAX_WORD]; /* インデックス文字列 */ byte title[MAX_WORD]; /* 見出し文字列 */ } INDEX; typedef struct honmon_t { /* 本文データ */ dword dblk; /* 本文ブロック番号 */ word dpos; /* 本文ブロック内位置 */ byte buf[MAX_BUFF]; /* 本文テキスト */ } HONMON; byte *base_path = ""; /* EBStudio基準ディレクトリ */ byte *out_path = ""; /* EBStudio出力ディレクトリ */ byte *sort_cmd = ""; /* ソートコマンドのパス */ int auto_kana = 0; /* 表記INDEXからかなINDEXを生成 */ int eb_type = 0; /* 0:EPWING, 1:電子ブック */ byte *book_title = ""; /* 書籍タイトル */ byte *book_type = ""; /* 書籍種別 */ byte *book_dir = ""; /* 書籍ディレクトリ名 */ byte *html_file = ""; /* 生成されるHTMLファイル名 */ byte *ebs_file = ""; /* 生成されるEBSファイル名 */ time_t start_time; /* 開始時刻 */ time_t stop_time; /* 終了時刻 */ int zg_start_unicode; /* 全角外字開始Unicodeコード */ int hg_start_unicode; /* 半角外字開始Unicodeコード */ int zg_start_ebhigh; /* 全角外字開始ebcode上位byte */ int hg_start_ebhigh; /* 半角外字開始ebcode上位byte */ int zg_orig_ebhigh; /* 元データの全角外字開始コード上位byte */ int zg_orig_eblow; /* 元データの全角外字開始コード下位byte */ int hg_orig_ebhigh; /* 元データの半角外字開始コード上位byte */ int hg_orig_eblow; /* 元データの半角外字開始コード下位byte */ dword fktitle_start_block; /* かな見出し開始ブロック番号 */ dword fhtitle_start_block; /* 表記見出し開始ブロック番号 */ dword fatitle_start_block; /* 英字見出し開始ブロック番号 */ int gen_kana; /* かなインデックスを作る */ int gen_hyoki; /* 表記インデックスを作る */ int gen_alpha; /* 英字インデックスを作る */ int have_auto_kana; /* auto_kana検索語がある */ int generate_gaiji_file(void); byte *gstr(byte *, int); byte *conv_title(byte *, byte *); int convert_index_data(FILE *, FILE *); int convert_title_data(FILE *, int); int generate_work_file(void); FILE *html_newfile(void); int html_close(FILE *); INDEX *read_index_data(FILE *, int, dword, INDEX *); HONMON *read_honmon_data(FILE *, HONMON *); int compare_position(INDEX *, HONMON *); byte *conv_honmon(byte *, byte *); byte *skipindent(byte *, int *); byte *indentstr(int); int generate_html_file(void); int generate_ebs_file(void); int parse_ini_file(void); int work_directory(void); int set_sort_command(void); int init(char *); void term(int); int main(int, char **); /* * 外字ダンプファイルからGaiji.xmlとGaijiMap.xmlを作る */ int generate_gaiji_file(void) { int first, unicode, ebhigh, eblow; byte *p, buf[MAX_DLINE]; FILE *fp, *ffp, *mfp; sprintf(buf, "%s%s", base_path, GMAP_FILE); if ((mfp = fopen(buf, "w")) == NULL) { message("外字マップファイル %s が新規作成できません\n", buf); return ERR; } sprintf(buf, "%s%s", base_path, GFONT_FILE); if ((ffp = fopen(buf, "w")) == NULL) { message("外字フォントファイル %s が新規作成できません\n", buf); return ERR; } fprintf(mfp, "\n"); fprintf(mfp, "\n"); fprintf(ffp, "\n"); fprintf(ffp, "\n"); message("外字ファイルを生成しています... "); first = TRUE; zg_start_unicode = 0xe000; zg_start_ebhigh = 0xa1; if ((fp = fopen(ZGAIJI_FILE, "r")) != NULL) { unicode = zg_start_unicode; ebhigh = zg_start_ebhigh; eblow = 0x21; while (fgets(buf, MAX_DLINE, fp) != NULL) { if (*buf == ' ' || *buf == '#') { fputs(buf, ffp); continue; } if (!strncmp(buf, "\n", ebhigh, eblow); first = FALSE; } else fprintf(ffp, "\n"); fprintf(ffp, "\n", ebhigh, eblow, unicode); fprintf(mfp, "\n", unicode, ebhigh, eblow); unicode++; if (eblow < 0x7e) { eblow++; } else { eblow = 0x21; ebhigh++; } } fclose(fp); if (!first) { fprintf(ffp, "\n"); fprintf(ffp, "\n"); } } first = TRUE; hg_start_unicode = unicode; hg_start_ebhigh = ebhigh + 1; if ((fp = fopen(HGAIJI_FILE, "r")) != NULL) { unicode = hg_start_unicode; ebhigh = hg_start_ebhigh; eblow = 0x21; while (fgets(buf, MAX_DLINE, fp) != NULL) { if (*buf == ' ' || *buf == '#') { fputs(buf, ffp); continue; } if (!strncmp(buf, "\n", ebhigh, eblow); first = FALSE; } else fprintf(ffp, "\n"); fprintf(ffp, "\n", ebhigh, eblow, unicode); fprintf(mfp, "\n", unicode, ebhigh, eblow); unicode++; if (eblow < 0x7e) { eblow++; } else { eblow = 0x21; ebhigh++; } } fclose(fp); if (!first) { fprintf(ffp, "\n"); fprintf(ffp, "\n"); } } fprintf(ffp, "\n"); fprintf(mfp, "\n"); fclose(ffp); fclose(mfp); message("終了しました\n"); return OK; } /* * 文字列を外字のUnicode表記に変換する */ byte * gstr(byte *str, int halfwidth) { int high, low, code; static byte buf[MAX_WORD]; if (*str == '<') str++; high = hexval(str); low = hexval(str+2); if (high < 0xa1) { sprintf(buf, "&#x%02X;&#x%02X;", high, low); return buf; } if (halfwidth) { code = hg_start_unicode; if (low < hg_orig_eblow) { low += 94; high--; } code += (high - hg_orig_ebhigh) * 94 + (low - hg_orig_eblow); } else { code = zg_start_unicode; if (low < zg_orig_eblow) { low += 94; high--; } code += (high - zg_orig_ebhigh) * 94 + (low - zg_orig_eblow); } sprintf(buf, "&#x%04X;", code); return buf; } /* * 見出し文字列をシフトJIS文字列に変換する */ byte * conv_title(byte *dst, byte *src) { int n, halfwidth; byte *p, *q; halfwidth = FALSE; p = src; q = dst; while (*p) { if (*p == '<') { if (p[1] >= 'A') { /* * 外字 */ q = addstr(q, gstr(p, halfwidth)); } else if (!strncmp(p+1, "1F04", 4)) { /* * 半角開始 */ halfwidth = TRUE; } else if (!strncmp(p+1, "1F05", 4)) { /* * 半角終了 */ halfwidth = FALSE; } else { /* * その他のタグはとりあえず無視 */ } p += 6; continue; } if (halfwidth && (n = tohan(p)) != ERR) { switch (n) { case '<': q = addstr(q, "<"); break; case '>': q = addstr(q, ">"); break; case '&': q = addstr(q, "&"); break; case '"': q = addstr(q, """); break; case '\'': q = addstr(q, "'"); break; default: *q++ = n; break; } p += 2; } else { *q++ = *p++; *q++ = *p++; } } *q = '\0'; return dst; } /* * インデックスデータを変換する */ int convert_index_data(FILE *ifp, FILE *ofp) { int complex, n, len, firsterr; dword dblk, tblk; word dpos, tpos; byte *p, buf[MAX_DLINE], str[MAX_WORD], tmp[MAX_WORD]; firsterr = TRUE; complex = FALSE; while ((p = fgets(buf, MAX_DLINE, ifp)) != NULL) { if (strncmp(p, "ID=", 3)) continue; if (!strncmp(p+3, "C0", 2)) break; if (!strncmp(p+3, "D0", 2)) { complex = TRUE; break; } } if (p == NULL) return ERR; while ((p = fgets(buf, MAX_DLINE, ifp)) != NULL) { if (*p == '\r' || *p == '\n' || !strncmp(p, "block#", 6) || !strncmp(p, "ID=", 3)) { continue; } if (complex) { if (!strncmp(p, "80:", 3)) continue; if (!strncmp(p, "C0:", 3) || !strncmp(p, "00:", 3)) p += 3; } if (*p == '[') { /* * 索引語が空っぽ。外字か? * (広辞苑第五版の表記インデックス末尾にある) */ continue; } p = getupto(p, tmp, '['); n = sscanf(p, "[%d]\t[%lx:%x][%lx:%x]", &len, &dblk, &dpos, &tblk, &tpos); if (n != 5) { if (firsterr) { write_log("\n"); firsterr = FALSE; } write_log("不正なインデックス行: %s", buf); continue; } if (dpos == 0x0800) { dpos = 0; dblk++; }; if (tpos == 0x0800) { tpos = 0; tblk++; } fprintf(ofp, "%08lX|%04X|%08lX|%04X|%s|\n", dblk, dpos, tblk, tpos, conv_title(str, tmp)); } return OK; } /* * 見出しデータを変換する */ int convert_title_data(FILE *ifp, int ofd) { int n, first, firsterr; long pos; dword tblk, start_block; word tpos; byte *p, *q, buf[MAX_DLINE], str[MAX_WORD]; first = TRUE; firsterr = TRUE; while ((p = fgets(buf, MAX_DLINE, ifp)) != NULL) { if (*p == '\r' || *p == '\n' || !strncmp(p, "[ID=", 4)) continue; if (sscanf(p, "[%lx:%x]", &tblk, &tpos) != 2) { if (firsterr) { write_log("\n"); firsterr = FALSE; } write_log("不正な見出し行: %s", buf); continue; } p = skipch(p, ']'); if (*p == '\r' || *p == '\n' || !strncmp(p, "<1F02>", 6) || !strncmp(p, "<1F03>", 6)) { continue; } if (first) { start_block = tblk; first = FALSE; } q = p; while (*q && *q != '\r' && *q != '\n') q++; *q = '\0'; n = strlen(p); if (n > 6 && !strncmp(&p[n-6], "<1F0A>", 6)) p[n-6] = '\0'; conv_title(str, p); pos = (long)((tblk - start_block) * 2048 + tpos) * 4; n = strlen(str) + 1; if (lseek(ofd, pos, SEEK_SET) < 0) return ERR; if (write(ofd, str, n) != n) return ERR; } return (int)start_block; } /* * インデックスおよび見出しの作業データファイルを生成する */ int generate_work_file(void) { int ofd, n; FILE *ifp, *ofp; byte buf[MAX_PATH]; struct stat st; if (stat(FKINDEX_FILE, &st) == 0) { if ((ifp = fopen(FKINDEX_FILE, "r")) == NULL) { message("かなインデックスファイル %s がオープンできません\n", FKINDEX_FILE); return ERR; } if ((ofp = fopen(FKINDEX_WORK, "w")) == NULL) { message("かなインデックス作業ファイル %s が新規作成できません\n", FKINDEX_WORK); return ERR; } message("かなインデックスデータを変換しています..."); if (convert_index_data(ifp, ofp) == ERR) { message("かなインデックスデータの変換に失敗しました\n"); return ERR; } message(" 終了しました\n"); fclose(ifp); fclose(ofp); message("かなインデックスデータをソートしています..."); sprintf(buf, "%s %s > %s", sort_cmd, FKINDEX_WORK, FKINDEX_DATA); system(buf); unlink(FKINDEX_WORK); message(" 終了しました\n"); } if (stat(FKTITLE_FILE, &st) == 0) { if ((ifp = fopen(FKTITLE_FILE, "r")) == NULL) { message("かな見出しファイル %s がオープンできません\n", FKTITLE_FILE); return ERR; } if ((ofd = open(FKTITLE_DATA, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) < 0) { message("かな見出しデータファイル %s が新規作成できません\n", FKTITLE_DATA); return ERR; } message("かな見出しデータを生成しています..."); if ((n = convert_title_data(ifp, ofd)) == ERR) { message("かな見出しデータの生成に失敗しました\n"); return ERR; } fktitle_start_block = n; message(" 終了しました\n"); fclose(ifp); close(ofd); } if (stat(FHINDEX_FILE, &st) == 0) { if ((ifp = fopen(FHINDEX_FILE, "r")) == NULL) { message("表記インデックスファイル %s がオープンできません\n", FHINDEX_FILE); return ERR; } if ((ofp = fopen(FHINDEX_WORK, "w")) == NULL) { message("表記インデックス作業ファイル %s が新規作成できません\n", FHINDEX_WORK); return ERR; } message("表記インデックスデータを変換しています..."); if (convert_index_data(ifp, ofp) == ERR) { message("表記インデックスデータの変換に失敗しました\n"); return ERR; } message(" 終了しました\n"); fclose(ifp); fclose(ofp); message("表記インデックスデータをソートしています..."); sprintf(buf, "%s %s > %s", sort_cmd, FHINDEX_WORK, FHINDEX_DATA); system(buf); unlink(FHINDEX_WORK); message(" 終了しました\n"); } if (stat(FHTITLE_FILE, &st) == 0) { if ((ifp = fopen(FHTITLE_FILE, "r")) == NULL) { message("表記見出しファイル %s がオープンできません\n", FHTITLE_FILE); return ERR; } if ((ofd = open(FHTITLE_DATA, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) < 0) { message("表記見出しデータファイル %s が新規作成できません\n", FHTITLE_DATA); return ERR; } message("表記見出し作業データを生成しています..."); if ((n = convert_title_data(ifp, ofd)) == ERR) { message("表記見出しデータの生成に失敗しました\n"); return ERR; } fhtitle_start_block = n; message(" 終了しました\n"); fclose(ifp); close(ofd); } if (stat(FAINDEX_FILE, &st) == 0) { if ((ifp = fopen(FAINDEX_FILE, "r")) == NULL) { message("英字インデックスファイル %s がオープンできません\n", FAINDEX_FILE); return ERR; } if ((ofp = fopen(FAINDEX_WORK, "w")) == NULL) { message("英字インデックス作業ファイル %s が新規作成できません\n", FAINDEX_WORK); return ERR; } message("英字インデックスデータを変換しています..."); if (convert_index_data(ifp, ofp) == ERR) { message("英字インデックスデータの変換に失敗しました\n"); return ERR; } message(" 終了しました\n"); fclose(ifp); fclose(ofp); message("英字インデックスデータをソートしています..."); sprintf(buf, "%s %s > %s", sort_cmd, FAINDEX_WORK, FAINDEX_DATA); system(buf); unlink(FAINDEX_WORK); message(" 終了しました\n"); } if (stat(FATITLE_FILE, &st) == 0) { if ((ifp = fopen(FATITLE_FILE, "r")) == NULL) { message("英字見出しファイル %s がオープンできません\n", FATITLE_FILE); return ERR; } if ((ofd = open(FATITLE_DATA, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) < 0) { message("英字見出しデータファイル %s が新規作成できません\n", FATITLE_DATA); return ERR; } message("英字見出し作業データを生成しています..."); if ((n = convert_title_data(ifp, ofd)) == ERR) { message("英字見出しデータの生成に失敗しました\n"); return ERR; } fatitle_start_block = n; message(" 終了しました\n"); fclose(ifp); close(ofd); } return OK; } /* * HTMLファイルを新規作成する */ FILE * html_newfile(void) { byte buf[MAX_PATH]; FILE *fp; sprintf(buf, "%s%s", base_path, html_file); if ((fp = fopen(buf, "w")) == NULL) { message("HTMLファイル %s が新規作成できません\n", buf); return NULL; } fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n", progname, version, date); fprintf(fp, "Dictionary\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "
\n"); return fp; } /* * HTMLファイルをクローズする */ int html_close(FILE *fp) { fprintf(fp, "
\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); return fclose(fp); } /* * インデックスと見出しを1件読む */ INDEX * read_index_data(FILE *fp, int fd, dword topblk, INDEX *ip) { int n; long pos; byte *p, buf[MAX_DLINE]; if ((p = fgets(buf, MAX_DLINE, fp)) == NULL) return NULL; n = sscanf(p, "%lx|%x|%lx|%x", &ip->dblk, &ip->dpos, &ip->tblk, &ip->tpos); if (n != 4) return NULL; p += 28; /* "xxxxxxxx|xxxx|yyyyyyyy|yyyy|"をスキップ */ getupto(p, ip->str, '|'); if (ip->dblk == ip->tblk && ip->dpos == ip->tpos) { /* * 見出しデータは本文の見出し行を共用する(広辞苑第五版) */ *ip->title = '\0'; } else { pos = (long)((ip->tblk - topblk) * 2048 + ip->tpos) * 4; if (lseek(fd, pos, SEEK_SET) < 0) return NULL; if (read(fd, ip->title, MAX_WORD) <= 0) return NULL; } return ip; } /* * 本文を1行読む */ HONMON * read_honmon_data(FILE *fp, HONMON *hp) { byte *p, *q, buf[MAX_BUFF]; if (fgets(buf, MAX_BUFF, fp) == NULL) return NULL; if (sscanf(buf, "[%lx:%x]", &hp->dblk, &hp->dpos) != 2) { hp->dblk = 0L; hp->dpos = 0; return hp; } if (hp->dpos == 0x0800) { hp->dpos = 0; hp->dblk++; } p = skipch(buf, ']'); q = p; while (*q && *q != '\r' && *q != '\n') q++; *q = '\0'; strcpy(hp->buf, p); return hp; } /* * インデックスの参照先と本文データの位置関係を比較する */ int compare_position(INDEX *ip, HONMON *dp) { byte *p; dword ipos, dpos; ipos = ip->dblk * 2048 + ip->dpos; dpos = dp->dblk * 2048 + dp->dpos; /* * 本文の行頭から * <1F09> * <1F41> * <1F61> * の並びが連続していて、 * インデックスの参照先がその直後の場合は * インデックスがその行頭を参照しているとみなす * (ジーニアス英和辞典など) */ if (ipos < dpos) return -1; p = dp->buf; while (*p && ipos > dpos) { if (!strncmp(p, "<1F09>", 6)) { p += 12; dpos += 4; continue; } if (!strncmp(p, "<1F41>", 6)) { p += 12; dpos += 4; } if (!strncmp(p, "<1F61>", 6)) { p += 6; dpos += 2; } break; } if (ipos > dpos) return 1; return 0; } /* * 本文データを変換する */ byte * conv_honmon(byte *dst, byte *src) { int n, halfwidth; dword dblk; word dpos; byte *p, *q, *r, *linetop; byte endtag[MAX_WORD], buf[MAX_DLINE], tmp[MAX_DLINE]; halfwidth = FALSE; p = src; q = dst; linetop = q; while (*p) { if (*p == '<') { if (p[1] == '1' && p[2] == 'F') { /* 1Fxx */ switch (p[3]) { case '0': switch (p[4]) { case '4': /* 1F04: 半角開始 */ halfwidth = TRUE; p += 6; break; case '5': /* 1F05: 半角終了 */ halfwidth = FALSE; p += 6; break; case '6': /* 1F06: 下添え字開始 */ q = addstr(q, ""); p += 6; break; case '7': /* 1F07: 下添え字終了 */ q = addstr(q, ""); p += 6; break; case 'A': /* 1F0A: 改行 */ q = addstr(q, "
"); p += 6; break; case 'E': /* 1F0E: 上添え字開始 */ q = addstr(q, ""); p += 6; break; case 'F': /* 1F0F: 上添え字終了 */ q = addstr(q, ""); p += 6; break; default: p += 6; break; } break; case '1': switch (p[4]) { case '0': /* 1F10: 分割禁止開始 */ q = addstr(q, ""); p += 6; break; case '1': /* 1F11: 分割禁止終了 */ q = addstr(q, ""); p += 6; break; case '4': /* 1F14 ... 1F15: 色見本 */ /* * "[色見本]"で置き換える */ p = skipstr(p+6, "<1F15>"); q = addstr(q, "[色見本]"); break; case 'A': /* 1F1A xxxx: タブ位置指定 */ case 'B': /* 1F1B xxxx: 字下げ・字上がり指定 */ case 'C': /* 1F1C xxxx: センタリング指定 */ p += 12; break; default: p += 6; break; } break; case '3': switch (p[4]) { case '9': /* 1F39 ... 1F59: カラー動画表示 */ /* * "[動画]"で置き換える */ p = skipstr(p+6, "<1F59>"); q = addstr(q, "[動画]"); break; case 'C': /* 1F3C ... 1F5C: インライン画像参照 */ /* * "[図版]"で置き換える */ p = skipstr(p+6, "<1F5C>"); q = addstr(q, "[図版]"); break; default: p += 6; break; } break; case '4': switch (p[4]) { case '1': /* 1F41 xxxx: 検索キー開始 */ p += 12; break; case '2': /* 1F42 text 1F62[xx:yy]: 別項目参照 */ p += 6; if (!strncmp(p, "→", 2)) p += 2; r = strstr(p, "<1F62>"); n = r - p; strncpy(buf, p, n); buf[n] = '\0'; p = r + 6; sscanf(p, "[%lx:%x]", &dblk, &dpos); p = skipch(p, ']'); sprintf(q, "%s", dblk, dpos, conv_honmon(tmp, buf)); q = endstr(q); break; case '4': /* 1F44 ... 1F64[xx:yy]: 図版参照 */ /* * "[図版]"で置き換える */ p = skipstr(p+6, "<1F64>"); p = skipch(p, ']'); q = addstr(q, "[図版]"); break; case 'A': /* 1F4A ... 1F6A: 音声参照 */ /* * "[音声]"で置き換える */ p = skipstr(p+6, "<1F6A>"); q = addstr(q, "[音声]"); break; case '5': /* 1F45 ... 1F65: 図版見出し */ case 'B': /* 1F4B ... 1F6B: カラー画像データ群参照 */ case 'C': /* 1F4C ... 1F6C: カラー画面データ群参照 */ case 'D': /* 1F4D ... 1F6D: カラー画面表示 */ case 'F': /* 1F4F ... 1F6F: カラー画面参照 */ /* * "[図版]"で置き換える */ sprintf(endtag, "<1F6%c>", p[4]); p = skipstr(p+6, endtag); q = addstr(q, "[図版]"); break; default: p += 6; break; } break; case '6': switch (p[4]) { case '1': /* 1F61: 検索キー終了 */ p += 6; break; default: p += 6; break; } break; case 'E': switch (p[4]) { case '0': /* 1FE0 xxxx ... 1FE1: 文字修飾 */ p += 12; break; default: p += 6; break; } break; default: p += 6; break; } } else if (p[1] >= 'A') { /* * 外字 */ q = addstr(q, gstr(p, halfwidth)); p += 6; } else { /* * その他のタグは無視 */ p += 6; } continue; } if (halfwidth && (n = tohan(p)) != ERR) { switch (n) { case '<': q = addstr(q, "<"); break; case '>': q = addstr(q, ">"); break; case '&': q = addstr(q, "&"); break; case '"': q = addstr(q, """); break; case '\'': q = addstr(q, "'"); break; default: *q++ = n; break; } p += 2; if (q - linetop >= MAX_HLINE && n == '.') { *q++ = '\n'; linetop = q; } } else { *q++ = *p++; *q++ = *p++; if (q - linetop >= MAX_HLINE && !strncmp(q-2, "。", 2)) { *q++ = '\n'; linetop = q; } } } if (q >= dst + 4 && !strncmp(q-4, "
", 4)) { /* * 最後の
は捨てる */ q -= 4; } *q = '\0'; return dst; } /* * 「1F41 xxxx 〜 1F61」または「1F41 xxxx 1F61 1FE0 xxxx 〜 1FE1」で * 囲まれたタイトルを取り出し、直後の位置を返す * ただし囲まれた範囲の長さが128バイト以上か * <1F61>が見つからない場合はタイトルとしない */ byte * get_title(byte *str, byte *title) { int n; byte *p, *r; if (strncmp(str, "<1F41>", 6)) { *title = '\0'; return str; } p = str + 12; /* <1F41>をスキップ */ r = strstr(p, "<1F61>"); if (r == NULL) { *title = '\0'; return str; } n = r - p; if (n >= MAX_WORD) { *title = '\0'; return str; } strncpy(title, p, n); title[n] = '\0'; p = r + 6; if (n == 0 && !strncmp(p, "<1FE0>", 6)) { /* * <1F41><1F61><1FE0> 〜 <1FE1>の形式 */ p += 12; r = strstr(p, "<1FE1>"); if (r == NULL) { *title = '\0'; return str; } n = r - p; strncpy(title, p, n); title[n] = '\0'; p = r + 6; } return p; } /* * 入力の字下げタグをスキップし、字下げ量を返す */ byte * skipindent(byte *str, int *indentp) { if (strncmp(str, "<1F09>", 6)) { *indentp = 0; return str; } *indentp = hexval(str+7) * 256 + hexval(str+9) - 1; return str + 12; } /* * 出力用字下げタグ文字列を作る */ byte * indentstr(int indent) { static byte buf[32]; sprintf(buf, "Ἁ�&#x%02x;", indent+1); return buf; } /* * honmon.txtと作業データファイルを突き合わせてHTMLファイルを生成する */ int generate_html_file(void) { int first_dt, needbr, indent, indent2; int have_preamble, have_indent, have_indent2; int yield_dt, new_content; int ktfd, htfd, atfd; dword ktop, htop, atop; byte *p, *title; byte buf[MAX_BUFF], tbuf[MAX_DLINE], tmp[MAX_DLINE]; byte istr[MAX_WORD], istr2[MAX_WORD]; FILE *fp, *honfp, *kifp, *hifp, *aifp; INDEX *kp, *hp, *ap, kidx, hidx, aidx; HONMON *dp, honmon; if ((fp = html_newfile()) == NULL) return ERR; if ((honfp = fopen(HONMON_FILE, "r")) == NULL) { message("本文ファイル %s がオープンできません\n", HONMON_FILE); return ERR; } gen_kana = FALSE; if ((kifp = fopen(FKINDEX_DATA, "r")) != NULL && (ktfd = open(FKTITLE_DATA, O_RDONLY|O_BINARY)) != -1) { gen_kana = TRUE; } gen_hyoki = FALSE; if ((hifp = fopen(FHINDEX_DATA, "r")) != NULL && (htfd = open(FHTITLE_DATA, O_RDONLY|O_BINARY)) != -1) { gen_hyoki = TRUE; } gen_alpha = FALSE; if ((aifp = fopen(FAINDEX_DATA, "r")) != NULL && (atfd = open(FATITLE_DATA, O_RDONLY|O_BINARY)) != -1) { gen_alpha = TRUE; } if (!gen_kana && !gen_hyoki && !gen_alpha) { message("かな/表記/英字いずれのインデックス/見出しもありません\n"); message("HTMLファイルの生成を中止します\n"); return ERR; } message("HTMLファイルを生成しています...\n"); have_auto_kana = FALSE; have_preamble = FALSE; first_dt = TRUE; needbr = FALSE; new_content = FALSE; kp = NULL; hp = NULL; ap = NULL; if (gen_kana) { ktop = fktitle_start_block; kp = read_index_data(kifp, ktfd, ktop, &kidx); } if (gen_hyoki) { htop = fhtitle_start_block; hp = read_index_data(hifp, htfd, htop, &hidx); } if (gen_alpha) { atop = fatitle_start_block; ap = read_index_data(aifp, atfd, atop, &aidx); } while ((dp = read_honmon_data(honfp, &honmon)) != NULL) { if (dp->dblk == 0L || *dp->buf == '\0') continue; p = dp->buf; if (!strcmp(p, "<1F02>") || !strcmp(p, "<1F03>")) { /* * これらはどこにあっても単独で出力する */ if (needbr) { fprintf(fp, "
\n"); needbr = FALSE; } if (!strcmp(p, "<1F02>")) { fprintf(fp, "ἂ\n"); new_content = TRUE; } else { fprintf(fp, "ἃ\n"); } needbr = FALSE; continue; } if (new_content) { /* * <1F02>の直後の行; 無条件にアンカーを作る * (研究社新英和中辞典など) */ fprintf(fp, "\n", dp->dblk, dp->dpos); new_content = FALSE; } have_indent = FALSE; have_indent2 = FALSE; *istr = '\0'; *istr2 = '\0'; if (!strncmp(dp->buf, "<1F09>", 6)) { p = skipindent(p, &indent); have_indent = TRUE; strcpy(istr, indentstr(indent)); } if (!strncmp(p, "<1F41>", 6)) { p = get_title(p, tmp); if (!strncmp(p, "<1F09>", 6)) { p = skipindent(p, &indent2); have_indent2 = TRUE; strcpy(istr2, indentstr(indent2)); } conv_honmon(tbuf, tmp); conv_honmon(buf, p); title = *tbuf? tbuf: buf; } else { *tbuf = '\0'; title = conv_honmon(buf, p); } while (kp && compare_position(kp, dp) < 0) { message("使われないかなインデックスがあります\n"); message(" 本文位置=[%08lX:%04X], インデックス=[%08lX:%04X]%s\n", dp->dblk, dp->dpos, kp->dblk, kp->dpos, kp->str); kp = read_index_data(kifp, ktfd, ktop, &kidx); } while (hp && compare_position(hp, dp) < 0) { message("使われない表記インデックスがあります\n"); message(" 本文位置=[%08lX:%04X], インデックス=[%08lX:%04X]%s\n", dp->dblk, dp->dpos, hp->dblk, hp->dpos, hp->str); hp = read_index_data(hifp, htfd, htop, &hidx); } while (ap && compare_position(ap, dp) < 0) { message("使われない英字インデックスがあります\n"); message(" 本文位置=[%08lX:%04X], インデックス=[%08lX:%04X]%s\n", dp->dblk, dp->dpos, ap->dblk, ap->dpos, ap->str); ap = read_index_data(aifp, atfd, atop, &aidx); } if (kp && compare_position(kp, dp) == 0 || hp && compare_position(hp, dp) == 0 || ap && compare_position(ap, dp) == 0) { /* * インデックスから参照されている */ if (have_preamble) { fprintf(fp, "\n

\n"); have_preamble = FALSE; } if (have_indent && indent > 0 || strlen(title) > MAX_WORD) { /* * 字下げされた位置が参照されているか * あるいはタイトルが128バイトを超えているので * 見出しとしては採用しない *
内に参照位置があったとみなし、 * あたらしい

を始める */ yield_dt = FALSE; } else { /* * 行頭位置が参照されており * タイトル長が128バイト以下なので * 新しい

を始める */ yield_dt = TRUE; } if (yield_dt) { if (first_dt) first_dt = FALSE; else fprintf(fp, "\n

\n"); fprintf(fp, "
%s
\n", dp->dblk, dp->dpos, title); } else { fprintf(fp, "\n

\n

\n"); } while (kp && compare_position(kp, dp) == 0) { fprintf(fp, "%s\n", *kp->title? kp->title: title, kp->str); kp = read_index_data(kifp, ktfd, ktop, &kidx); } while (hp && compare_position(hp, dp) == 0) { fprintf(fp, "%s\n", *hp->title? hp->title: title, hp->str); if (auto_kana && iskanastr(hp->str)) { fprintf(fp, "%s\n", *hp->title? hp->title: title, hp->str); have_auto_kana = TRUE; } hp = read_index_data(hifp, htfd, htop, &hidx); } while (ap && compare_position(ap, dp) == 0) { fprintf(fp, "%s\n", *ap->title? ap->title: title, ap->str); ap = read_index_data(aifp, atfd, atop, &aidx); } if (yield_dt) { fprintf(fp, "

\n"); if (*tbuf && *buf) fprintf(fp, "%s%s", istr2, buf); else fprintf(fp, " "); } else { fprintf(fp, "%s%s%s%s", istr, tbuf, istr2, buf); } have_indent = FALSE; have_indent2 = FALSE; *istr = '\0'; *istr2 = '\0'; needbr = TRUE; continue; } if (needbr) { fprintf(fp, "
\n"); needbr = FALSE; } if (first_dt && !have_preamble) { /* * 最初の

より前に内容があった */ fprintf(fp, "

\n"); have_preamble = TRUE; } fprintf(fp, "%s%s%s%s", istr, tbuf, istr2, buf); needbr = TRUE; } fprintf(fp, "\n"); if (gen_kana) { fclose(kifp); close(ktfd); } if (gen_hyoki) { fclose(hifp); close(htfd); } if (gen_alpha) { fclose(aifp); close(atfd); } fclose(honfp); html_close(fp); message("HTMLファイルの生成が終了しました\n"); return OK; } /* * EBStudio定義ファイルを生成する */ int generate_ebs_file(void) { byte buf[MAX_PATH]; FILE *fp; sprintf(buf, "%s%s", base_path, ebs_file); if ((fp = fopen(buf, "w")) == NULL) { message("EBStudio定義ファイル %s が新規作成できません\n", buf); return ERR; } message("EBSファイルを生成しています... "); fprintf(fp, "InPath=%s\n", base_path); fprintf(fp, "OutPath=%s\n", out_path); fprintf(fp, "IndexFile=\n"); fprintf(fp, "Copyright=\n"); fprintf(fp, "GaijiFile=$(BASE)\\%s\n", GFONT_FILE); fprintf(fp, "GaijiMapFile=$(BASE)\\%s\n", GMAP_FILE); fprintf(fp, "EBType=%d\n", eb_type); fprintf(fp, "WordSearchHyoki=%d\n", (gen_hyoki || gen_alpha)? 1: 0); fprintf(fp, "WordSearchKana=%d\n", (gen_kana || have_auto_kana)? 1: 0); fprintf(fp, "EndWordSearchHyoki=%d\n", (gen_hyoki || gen_alpha)? 1: 0); fprintf(fp, "EndWordSearchKana=%d\n", (gen_kana || have_auto_kana)? 1: 0); fprintf(fp, "KeywordSearch=0\n"); fprintf(fp, "ComplexSearch=0\n"); fprintf(fp, "topMenu=0\n"); fprintf(fp, "singleLine=1\n"); fprintf(fp, "kanaSep1=【\n"); fprintf(fp, "kanaSep2=】\n"); fprintf(fp, "hyokiSep=0\n"); fprintf(fp, "makeFig=0\n"); fprintf(fp, "inlineImg=0\n"); fprintf(fp, "paraHdr=0\n"); fprintf(fp, "ruby=1\n"); fprintf(fp, "paraBr=0\n"); fprintf(fp, "subTitle=0\n"); fprintf(fp, "dfnStyle=0\n"); fprintf(fp, "srchUnit=1\n"); fprintf(fp, "linkChar=0\n"); fprintf(fp, "arrowCode=222A\n"); fprintf(fp, "eijiPronon=1\n"); fprintf(fp, "eijiPartOfSpeech=1\n"); fprintf(fp, "eijiBreak=1\n"); fprintf(fp, "eijiKana=0\n"); fprintf(fp, "leftMargin=0\n"); fprintf(fp, "indent=0\n"); fprintf(fp, "tableWidth=480\n"); fprintf(fp, "StopWord=\n"); fprintf(fp, "delBlank=1\n"); fprintf(fp, "delSym=1\n"); fprintf(fp, "delChars=\n"); fprintf(fp, "refAuto=0\n"); fprintf(fp, "titleWord=0\n"); fprintf(fp, "autoWord=0\n"); fprintf(fp, "autoEWord=0\n"); fprintf(fp, "HTagIndex=0\n"); fprintf(fp, "DTTagIndex=1\n"); fprintf(fp, "dispKeyInSelList=0\n"); fprintf(fp, "titleOrder=0\n"); fprintf(fp, "omitHeader=0\n"); fprintf(fp, "addKana=1\n"); fprintf(fp, "autoKana=0\n"); fprintf(fp, "withHeader=0\n"); fprintf(fp, "optMono=0\n"); fprintf(fp, "Size=20000;30000;100;3000000;20000;20000;20000;1000;1000;1000;1000\n"); fprintf(fp, "Book=%s;%s;%s;_;", book_title, book_dir, book_type); fprintf(fp, "_;GAI16H00;GAI16F00;_;_;_;_;_;_;\n"); fprintf(fp, "Source=$(BASE)\\%s;本文;_;HTML;\n", html_file); fclose(fp); message("終了しました\n"); return OK; } /* * 設定ファイルを読み込む */ int parse_ini_file(void) { int n, lineno, ret; byte *p; byte key[MAX_WORD], val[MAX_PATH], buf[BUFSIZ]; FILE *fp; if ((fp = fopen(INI_FILE, "r")) == NULL) { message("設定ファイル %s がオープンできません\n", INI_FILE); return ERR; } ret = OK; lineno = 0; while (fgets((char *)buf, BUFSIZ, fp) != NULL) { lineno++; p = skipsp(buf); if (*p == '#' || *p == '\r' || *p == '\n') continue; p = getuptos(p, key, " \t=#"); p = skipch(p, '='); p = skipsp(p); p = getuptos(p, val, "\t#"); n = atoi(val); if (!strcmp(key, "BASEPATH")) { if (p[-1] != '/' && p[-1] != '\\') strcat(val, "\\"); base_path = strdup(val); } else if (!strcmp(key, "OUTPATH")) { if (p[-1] != '/' && p[-1] != '\\') strcat(val, "\\"); out_path = strdup(val); } else if (!strcmp(key, "SORTCMD")) { sort_cmd = strdup(val); } else if (!strcmp(key, "AUTOKANA")) { auto_kana = n; } else if (!strcmp(key, "EBTYPE")) { eb_type = n; } else if (!strcmp(key, "BOOKTITLE")) { book_title = strdup(val); for (p = book_title; *p; p += 2) { if ((*p & 0x80) == 0) break; } if (*p) { message("書籍タイトルに1バイト文字が含まれています(%d行め)\n", lineno); ret = ERR; } } else if (!strcmp(key, "BOOKTYPE")) { book_type = strdup(val); if (strcmp(book_type, "国語辞典") && strcmp(book_type, "漢和辞典") && strcmp(book_type, "英和辞典") && strcmp(book_type, "和英辞典") && strcmp(book_type, "現代用語辞典") && strcmp(book_type, "一般書物") && strcmp(book_type, "類語辞典")) { message("未知の書籍種別が指定されています(%d行め)\n", lineno); ret = ERR; } } else if (!strcmp(key, "BOOKDIR")) { book_dir = strdup(val); if (strlen(book_dir) > 8) { message("書籍ディレクトリ名が8バイトを超えています(%d行め)\n", lineno); ret = ERR; } for (p = book_dir; *p; p++) { if (*p >= 'A' && *p <= 'Z') continue; if (*p >= '0' && *p <= '9' || *p == '_') continue; break; } if (*p) { message("書籍ディレクトリ名に不正な文字(A-Z0-9_以外)が含まれています(%d行め)\n", lineno); ret = ERR; } if (ret != ERR) { sprintf(buf, "%s.html", book_dir); html_file = strdup(buf); sprintf(buf, "%s.ebs", book_dir); ebs_file = strdup(buf); } } else { message("設定ファイルに不正な行があります(%d行め)\n", lineno); ret = ERR; } } fclose(fp); message("変換設定は以下のとおりです\n"); message(" BASEPATH = %s\n", base_path); message(" OUTPATH = %s\n", out_path); message(" SORTCMD = %s\n", sort_cmd); message(" AUTOKANA = %d\n", auto_kana); message(" EBTYPE = %d\n", eb_type); message(" BOOKTITLE = %s\n", book_title); message(" BOOKTYPE = %s\n", book_type); message(" BOOKDIR = %s\n", book_dir); message(" 生成されるHTMLファイル = %s\n", html_file); message(" 生成されるEBSファイル = %s\n", ebs_file); return ret; } /* * ファイル出力先ディレクトリを作る */ int work_directory(void) { int i; char *p, path[MAX_PATH], subpath[MAX_PATH]; struct stat st; if (*base_path && strcmp(base_path, "\\") && strcmp(base_path + 1, ":\\")) { strcpy(path, base_path); p = &path[strlen(path) - 1]; if (*p == '/' || *p == '\\') *p = '\0'; if (stat(path, &st) < 0) { if (mkdir(path) < 0) { message("基準ディレクトリ %s が作れません\n", path); return ERR; } message("基準ディレクトリ %s を新規作成しました\n", path); } else if ((st.st_mode & S_IFMT) != S_IFDIR) { message("基準ディレクトリ %s と同名のファイルがあります\n", path); return ERR; } } if (*out_path && strcmp(out_path, "\\") && strcmp(out_path + 1, ":\\")) { strcpy(path, out_path); p = &path[strlen(path) - 1]; if (*p == '/' || *p == '\\') *p = '\0'; if (stat(path, &st) < 0) { if (mkdir(path) < 0) { message("出力先ディレクトリ %s が作れません\n", path); return ERR; } message("出力先ディレクトリ %s を新規作成しました\n", path); } else if ((st.st_mode & S_IFMT) != S_IFDIR) { message("出力先ディレクトリ %s と同名のファイルがあります\n", path); return ERR; } } return OK; } /* * 利用可能なソートコマンドを設定する */ int set_sort_command(void) { char **p; struct stat st; static char *sort_cmd_cand[] = { "", "C:\\Windows\\System32\\sort.exe", "C:\\WinNT\\System32\\sort.exe", "C:\\Windows\\command\\sort.exe", NULL }; if (sort_cmd && *sort_cmd) sort_cmd_cand[0] = sort_cmd; for (p = sort_cmd_cand; *p; p++) { if (stat(*p, &st) == 0) { sort_cmd = *p; return OK; } } message("ソートコマンドが見つかりません\n"); return ERR; } /* * 初期化 */ int init(char *cmd_path) { char *p, path[MAX_PATH]; strcpy(path, cmd_path); p = &path[strlen(path) - 1]; while (p > path && *p != '\\') p--; *p = '\0'; if (!strcmp(path + 1, ":")) strcat(path, "\\"); if (chdir(path) < 0) { printf("作業ディレクトリ %s への移動に失敗しました\n", path); return ERR; } time(&start_time); write_log("開始時刻: %s", ctime(&start_time)); message("作業ディレクトリ %s に移動しました\n", path); return OK; } /* * 終了処理 */ void term(int status) { time_t t; if (status == OK) message("変換処理が終了しました\n"); else message("変換処理に失敗しました\n"); time(&stop_time); t = stop_time - start_time; write_log("終了時刻: %s", ctime(&stop_time)); message("経過時間: %d:%02d\n", (int)(t / 60), (int)(t % 60)); if (status == OK) { message("※ %s%s を入力としてEBStudioを実行してください\n", base_path, ebs_file); } write_log("\n"); exit(status == ERR? 1: 0); } /* * メイン */ int main(int ac, char **av) { if (init(av[0]) == ERR) term(ERR); if (parse_ini_file() == ERR) term(ERR); if (work_directory() == ERR) term(ERR); if (set_sort_command() == ERR) term(ERR); if (generate_gaiji_file() == ERR) term(ERR); if (generate_work_file() == ERR) term(ERR); if (generate_html_file() == ERR) term(ERR); if (generate_ebs_file() == ERR) term(ERR); term(OK); }