/* * ランダムハウス英語辞典Toolkit 本体プログラム srd2html * Written by Junn Ohta (ohta@sdg.mdd.ricoh.co.jp), Public Domain. */ char *progname = "srd2html"; char *version = "pre-release4a"; char *date = "2004/12/25"; #include #include #include #include #include #include #include #include #include #include #include typedef unsigned char byte; typedef unsigned int word; #ifndef O_BINARY #define O_BINARY 0 #endif #define OK 0 #define ERR (-1) #define TRUE 1 #define FALSE 0 /* -------------------- ユーティリティー関数 -------------------- */ #define LOG_FILE "srd2html.log" /* ログファイル */ #define MAX_WORD 128 /* 単語の最大長 */ #define MAX_POOL 4096 /* 文字列プールの割り当て単位 */ byte *pool = NULL; /* 文字列プール */ byte *pfree = NULL; /* 文字列プールの空き領域先頭 */ /* * 1バイト→2バイト変換表 */ byte *han2zen[] = { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", " ", "!", "”", "#", "$", "%", "&", "’", "(", ")", "*", "+", ",", "−", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "¥", "]", "^", "_", "‘", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "〜", "" }; int hexval(byte *); byte *skipsp(byte *); byte *skipch(byte *, int); byte *skipwch(byte *, byte *); byte *endstr(byte *); byte *addstr(byte *, byte *); byte *tozen(byte *, byte *); byte *getuptos(byte *, byte *, byte *); byte *getupto(byte *, byte *, byte); byte *getuptow(byte *, byte *, byte *); byte *getqword(byte *, byte *); byte *getnumber(byte *, byte *); byte *removetag(byte *); byte *getidxword(byte *buf, byte *word); byte *strpool(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; } /* * 指定2バイト文字まで読み飛ばし、その次の位置を返す */ byte * skipwch(byte *str, byte *wch) { while (*str && (*str != *wch || str[1] != wch[1])) { if (*str & 0x80) str++; str++; } if (*str == *wch && str[1] == wch[1]) str += 2; return str; } /* * 文字列の末尾の位置を返す */ byte * endstr(byte *str) { while (*str) str++; return str; } /* * バッファに文字列を追加し、その末尾を返す(NULで終了はしない) */ byte * addstr(byte *dst, byte *str) { while (*str) *dst++ = *str++; return dst; } /* * 1バイト英数字列を2バイト英数字列に変換する */ byte * tozen(byte *dst, byte *src) { byte *p, *q; p = src; q = dst; while (*p) { if (*p < 0x80) { *q++ = han2zen[*p][0]; *q++ = han2zen[*p][1]; } p++; } *q = '\0'; return dst; } /* * 区切り文字セットまでの単語を切り出し、区切り文字の位置を返す */ 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; *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') *q++ = *p++; *q = '\0'; return p; } /* * 2バイト区切り文字までのgetupto */ byte * getuptow(byte *buf, byte *word, byte *stopw) { byte *p, *q; p = buf; q = word; while (*p && *p != '\r' && *p != '\n') { if (p[0] == stopw[0] && p[1] == stopw[1]) break; *q++ = *p++; *q++ = *p++; } *q = '\0'; return p; } /* * 二重引用符で囲まれた単語を切り出し、閉じる引用符直後の位置を返す */ byte * getqword(byte *buf, byte *word) { byte *p, *q; p = buf; q = word; if (*p == '"') p++; while (*p && *p != '"') { if (*p == '\\' && p[1] != '\0') p++; if (*p & 0x80) *q++ = *p++; *q++ = *p++; } *q = '\0'; if (*p == '"') p++; return p; } /* * 文字列から十進数値列を取り出す */ byte * getnumber(byte *buf, byte *num) { byte *p, *q; p = buf; q = num; while (*p && isdigit(*p)) *q++ = *p++; *q = '\0'; return p; } /* * 文字列からタグ表記を取り除く * (元の文字列を上書きする) */ byte * removetag(byte *buf) { byte *top, *p, *q; top = p = q = buf; while (*p) { if (*p == '<') { p = skipch(p, '>'); continue; } if (*p & 0x80) *q++ = *p++; *q++ = *p++; } *q = '\0'; return top; } /* * 成句/用例キーワードを切り出す */ byte * getidxword(byte *buf, byte *word) { byte *p, *q, ch; p = buf; q = word; while (*p && !isalnum(*p)) { if (*p == '<') { /* * タグをスキップ */ while (*p && *p != '>') p++; if (*p) p++; continue; } if (*p == '#') { /* * #nn# をスキップ */ p += 4; continue; } p++; } if (!*p) return NULL; while (*p && isalnum(*p)) { ch = *p++; if (islower(ch)) ch = ch - 'a' + 'A'; *q++ = han2zen[ch][0]; *q++ = han2zen[ch][1]; } *q = '\0'; return p; } /* * 文字列をプールに格納してそのアドレスを返す(解放を考慮しないstrdup) */ byte * strpool(byte *str) { int len; byte *p; if (str == NULL) return NULL; len = strlen(str) + 1; if (pool == NULL || pfree + len > pool + MAX_POOL) { pool = (byte *)malloc(MAX_POOL); /* 以前のpoolの値は忘れる */ if (pool == NULL) return NULL; pfree = pool; } p = pfree; pfree += len; return strcpy(p, str); } /* * メッセージをログファイルに書く */ 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 LST_START 0x100L /* 索引語リスト開始位置 */ #define REV_LF 0xf5 /* 0x0a(LF)のビット反転 */ /* * 索引語リストエントリ */ typedef struct lent_t { long dpos; /* 本文データ位置 */ long dlen; /* 本文データサイズ */ byte fkey[128]; /* 前方一致キー */ byte rkey[128]; /* 後方一致キー */ byte kstr[256]; /* 見出し文字列 */ } LENT; /* * 成句/用例リストエントリ */ typedef struct ilent_t { word entid; /* 順序番号 */ long nent; /* 同一単語個数??? */ long dpos; /* 本文データ位置 */ byte idkey[24]; /* 構成単語文字列(最大17文字) */ } ILENT; long linepos = 0L; /* 現在行先頭のファイル位置 */ long curpos = 0L; /* 現在のファイル位置 */ long filesize = -1L; /* dic_openファイルサイズ */ FILE *dic_open(char *, char *); int dic_close(FILE *); byte *dic_getline(FILE *, byte *); long dic_linepos(void); long dic_filesize(void); FILE *lst_open(char *, char *); int lst_close(FILE *); LENT *lst_getentry(FILE *, LENT *); int dat_open(char *, char *); int dat_close(int); int dat_splitfile(char *, char *, int, long, long); FILE *qj_newfile(char *); FILE *qj_open(char *); int qj_close(FILE *); long qj_getline(FILE *, byte *); FILE *hl_newfile(char *); FILE *hl_open(char *); int hl_close(FILE *); byte *hl_getline(FILE *, byte *); FILE *html_newfile(char *, char *); int html_close(FILE *); FILE *menu_newfile(char *, char *, char *); int menu_close(FILE *); FILE *pl_newfile(char *, char *); int pl_putentry(FILE *, char *, char *, char *, long, long); int pl_close(FILE *, long, long); /* * 本文ファイルをオープンする */ FILE * dic_open(char *dir, char *file) { byte buf[MAX_PATH]; FILE *fp; struct stat st; sprintf(buf, "%s%s", dir, file); if ((fp = fopen(buf, "rb")) == NULL) { message("本文ファイル %s がオープンできません\n", buf); return NULL; } if (fstat(fileno(fp), &st) < 0) { message("本文ファイル %s へのfstat()に失敗しました\n", buf); return NULL; } linepos = 0L; curpos = 0L; filesize = (long)st.st_size; return fp; } /* * 本文ファイルをクローズする */ int dic_close(FILE *fp) { return fclose(fp); } /* * 本文データを1行読み込んで返す */ byte * dic_getline(FILE *fp, byte *buf) { int c; byte *p; linepos = curpos; p = buf; while ((c = getc(fp)) != EOF) { curpos++; if (c == REV_LF) { *p = '\0'; return buf; } *p++ = ~c; } return NULL; } /* * dic_getline()で最後に読んだ行頭のファイル内での位置を返す */ long dic_linepos(void) { return linepos; } /* * dic_open()でオープンした辞書のサイズを返す */ long dic_filesize(void) { return filesize; } /* * 索引語リストファイルをオープンする */ FILE * lst_open(char *dir, char *file) { byte buf[MAX_PATH]; FILE *fp; sprintf(buf, "%s%s", dir, file); if ((fp = fopen(buf, "rb")) == NULL) { message("索引語リストファイル %s がオープンできません\n", buf); return NULL; } fseek(fp, LST_START, SEEK_SET); return fp; } /* * 索引語リストファイルをクローズする */ int lst_close(FILE *fp) { return fclose(fp); } /* * 索引語リストデータを1件読み込む */ LENT * lst_getentry(FILE *fp, LENT *lp) { int i, len; byte *p; if (getc(fp) == EOF) return NULL; getc(fp); len = getc(fp); p = lp->fkey; while (len-- > 0) *p++ = getc(fp); *p = '\0'; getc(fp); getc(fp); len = getc(fp); p = lp->rkey; while (len-- > 0) *p++ = getc(fp); *p = '\0'; getc(fp); getc(fp); lp->dpos = 0L; for (i = 0; i < 32; i += 8) lp->dpos |= ((long)getc(fp) << i); getc(fp); getc(fp); lp->dlen = 0L; for (i = 0; i < 32; i += 8) lp->dlen |= ((long)getc(fp) << i); for (i = 0; i < 8; i++) getc(fp); len = getc(fp); p = lp->kstr; while (len-- > 0) *p++ = getc(fp); *p = '\0'; return lp; } /* * 図版/音声データファイルをオープンする */ int dat_open(char *dir, char *file) { byte buf[MAX_PATH]; int fd; sprintf(buf, "%s%s", dir, file); if ((fd = open(buf, O_RDONLY|O_BINARY)) < 0) { message("データファイル %s がオープンできません\n", buf); return -1; } return fd; } /* * 図版/音声データファイルをクローズする */ int dat_close(int fd) { return close(fd); } /* * 図版/音声データを個別ファイルに書き出す */ int dat_splitfile(char *dir, char *file, int ifd, long dpos, long dlen) { int ofd, n; byte buf[MAX_PATH]; char *msg, databuf[BUFSIZ]; sprintf(buf, "%s%s", dir, file); if ((ofd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 0644)) < 0) { message("データファイル %s が新規作成できません\n", buf); return ERR; } if (lseek(ifd, dpos, SEEK_SET) < 0) { msg = "データファイルのlseek()に失敗しました\n"; goto err; } while (dlen > 0L) { n = dlen > (long)BUFSIZ? BUFSIZ: (int)dlen; if (read(ifd, databuf, n) != n) { msg = "データファイルの読み込みに失敗しました\n"; goto err; } if (write(ofd, databuf, n) != n) { msg = "個別データファイルの書き出しに失敗しました\n"; goto err; } dlen -= (long)n; } close(ofd); return OK; err: message(msg); return ERR; } /* * 項目内ジャンプデータファイルを新規作成する */ FILE * qj_newfile(char *file) { FILE *fp; if ((fp = fopen(file, "w")) == NULL) { message("項目内ジャンプデータファイル %s が新規作成できません\n", file); return NULL; } return fp; } /* * 項目内ジャンプデータファイルを読み込みでオープンする */ FILE * qj_open(char *file) { FILE *fp; if ((fp = fopen(file, "r")) == NULL) { message("項目内ジャンプデータファイル %s がオープンできません\n", file); return NULL; } return fp; } /* * 項目内ジャンプデータファイルをクローズする */ int qj_close(FILE *fp) { return fclose(fp); } /* * 項目内ジャンプデータファイルから1件のデータを読み込む */ long qj_getline(FILE *fp, byte *buf) { long qjpos; if (fgets(buf, MAX_DLINE, fp) == NULL) return -1L; qjpos = -1L; sscanf(buf, "%ld|", &qjpos); return qjpos; } /* * ハイパーリンクデータファイルを新規作成する */ FILE * hl_newfile(char *file) { FILE *fp; if ((fp = fopen(file, "w")) == NULL) { message("ハイパーリンクデータファイル %s が新規作成できません\n", file); return NULL; } return fp; } /* * ハイパーリンクデータファイルを読み込みでオープンする */ FILE * hl_open(char *file) { FILE *fp; if ((fp = fopen(file, "r")) == NULL) { message("ハイパーリンクデータファイル %s がオープンできません\n", file); return NULL; } return fp; } /* * ハイパーリンクデータファイルをクローズする */ int hl_close(FILE *fp) { return fclose(fp); } /* * 項目内ジャンプデータファイルから1件のデータを読み込む */ byte * hl_getline(FILE *fp, byte *buf) { byte *p; static byte itemno[MAX_WORD]; if (fgets(buf, MAX_DLINE, fp) == NULL) return NULL; p = skipsp(buf); getupto(p, itemno, '|'); return itemno; } /* * 出力HTMLファイルを新規作成する */ FILE * html_newfile(char *dir, char *file) { byte buf[MAX_PATH]; FILE *fp; sprintf(buf, "%s%s", dir, 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, "RandomHouse 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); } /* * メニューファイルを新規作成する */ FILE * menu_newfile(char *dir, char *file, char *title) { byte buf[MAX_PATH]; FILE *fp; sprintf(buf, "%s%s", dir, file); if ((fp = fopen(buf, "w")) == NULL) { message("メニューファイル %s が新規作成できません\n", buf); return NULL; } fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n", progname, version, date); fprintf(fp, "%s\n", title); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "

%s

\n", title); return fp; } /* * メニューファイルをクローズする */ int menu_close(FILE *fp) { fprintf(fp, "

\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); return fclose(fp); } /* * iTunesプレイリストファイルを新規作成する */ FILE * pl_newfile(char *dir, char *file) { byte *p, buf[MAX_PATH]; FILE *fp; sprintf(buf, "%s%s", dir, file); if ((fp = fopen(buf, "w")) == NULL) { message("iTunesプレイリストファイル %s が新規作成できません\n", buf); return NULL; } strcpy(buf, dir); for (p = buf; *p; p++) { if (*p == '\\') *p = '/'; } fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\tMajor Version1\n"); fprintf(fp, "\tMinor Version1\n"); fprintf(fp, "\tApplication Version4.7\n"); fprintf(fp, "\tMusic Folderfile://localhost/%swav/\n", buf); fprintf(fp, "\tLibrary Persistent IDB56BCEAE0E952195\n"); fprintf(fp, "\tTracks\n"); fprintf(fp, "\t\n"); return fp; } /* * iTunesプレイリストファイルにエントリを書き出す */ int pl_putentry(FILE *fp, char *path, char *snd, char *dir, long dpos, long no) { fprintf(fp, "\t\t%ld\n", no); fprintf(fp, "\t\t\n"); fprintf(fp, "\t\t\tTrack ID%ld\n", no); fprintf(fp, "\t\t\tName%08lx\n", dpos); fprintf(fp, "\t\t\tArtist%s\n", snd); fprintf(fp, "\t\t\tAlbum%s\n", dir); fprintf(fp, "\t\t\tKindAIFF audio file\n"); fprintf(fp, "\t\t\tBit Rate176\n"); fprintf(fp, "\t\t\tSample Rate11025\n"); fprintf(fp, "\t\t\tLocationfile://localhost/%s%s/%08lx.aifc\n", path, dir, dpos); fprintf(fp, "\t\t\tFile Folder Count-1\n"); fprintf(fp, "\t\t\tLibrary Folder Count-1\n"); fprintf(fp, "\t\t\n"); return OK; } /* * iTunesプレイリストファイルをクローズする */ int pl_close(FILE *fp, long begno, long endno) { long n; fprintf(fp, "\t\n"); fprintf(fp, "\tPlaylists\n"); fprintf(fp, "\t\n"); fprintf(fp, "\t\t\n"); fprintf(fp, "\t\t\tNameLibrary\n"); fprintf(fp, "\t\t\tMaster\n"); fprintf(fp, "\t\t\tPlaylist ID01\n"); fprintf(fp, "\t\t\tPlaylist Persistent IDB66BCEAE0E952195\n"); fprintf(fp, "\t\t\tAll Items\n"); fprintf(fp, "\t\t\tPlaylist Items\n"); fprintf(fp, "\t\t\t\n"); for (n = begno; n <= endno; n++) { fprintf(fp, "\t\t\t\t\n"); fprintf(fp, "\t\t\t\t\tTrack ID%ld\n", n); fprintf(fp, "\t\t\t\t\n"); } fprintf(fp, "\t\t\t\n"); fprintf(fp, "\t\t\n"); fprintf(fp, "\t\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); return fclose(fp); } /* -------------------- 外字処理 -------------------- */ #define MAX_GLINE 1024 /* 外字データファイルの最大行長 */ #define GIDX(n) (((n) >= 0 && (n) <= 6)? (n): ((n) == 99)? 7: -1) typedef struct gspecial_t { byte *name; /* 特殊外字参照名 */ byte *str; /* 外字文字列 */ struct gspecial_t *next; /* 次要素 */ } GSP; byte *gtable[8][256]; /* 外字置換表 */ GSP *gsptop = NULL; /* 特殊外字置換リスト */ int process_gaiji(char *, char *, char *, char *); byte *gstr(int, int); byte *gstrbyname(byte *); byte *buildstr(byte *, byte *); /* * 外字表を初期化し、EBStudioのための外字関連ファイルを生成する */ int process_gaiji(char *dir, char *gtfile, char *gmfile, char *gffile) { int i, j, n, ch, times; int ehigh, elow, unino, gset, gcode, issp; GSP *gsp; byte *p, *q; byte name[MAX_WORD], str[MAX_WORD], hz[MAX_WORD], uni[MAX_WORD]; byte file[MAX_PATH], buf[MAX_GLINE]; fpos_t pos; FILE *fp, *mfp, *ffp; if ((fp = fopen(gtfile, "r")) == NULL) { message("外字データファイル %s がオープンできません\n", buf); return ERR; } sprintf(file, "%s%s", dir, gmfile); if ((mfp = fopen(file, "w")) == NULL) { message("外字マップファイル %s が新規作成できません\n", buf); fclose(fp); return ERR; } sprintf(file, "%s%s", dir, gffile); if ((ffp = fopen(file, "w")) == NULL) { message("外字フォントファイル %s が新規作成できません\n", buf); fclose(fp); fclose(ffp); return ERR; } message("外字データを変換しています..."); ehigh = 0xa1; elow = 0x21; unino = 0xe000; fprintf(mfp, "\n"); fprintf(mfp, "\n"); fprintf(ffp, "\n"); fprintf(ffp, "\n"); fprintf(ffp, "\n", ehigh, elow); p = fgets(buf, MAX_GLINE, fp); while (p != NULL) { if (strncmp(p, "CHAR:", 5)) { p = fgets(buf, MAX_GLINE, fp); continue; } p = getupto(p+5, name, ':') + 1; if (sscanf(name, "G%d-%x", &gset, &gcode) == 2 && GIDX(gset) != -1 && gcode >= 0x00 && gcode <= 0xff) { issp = FALSE; } else { issp = TRUE; } if (*p == '"') { getqword(p+1, str); if (issp) { gsp = (GSP *)malloc(sizeof(GSP)); gsp->name = strpool(name); gsp->str = strpool(str); gsp->next = gsptop; gsptop = gsp; } else { gtable[GIDX(gset)][gcode] = strpool(str); } p = fgets(buf, MAX_GLINE, fp); continue; } if (*p != 'H') { p = fgets(buf, MAX_GLINE, fp); continue; } p = skipch(p, ':'); if (!strncmp(p, "U+", 2)) getupto(p+2, uni, ':'); else sprintf(uni, "%04X", unino++); sprintf(str, "&#x%s;", uni); if (issp) { gsp = (GSP *)malloc(sizeof(GSP)); gsp->name = strpool(name); gsp->str = strpool(str); gsp->next = gsptop; gsptop = gsp; } else { gtable[GIDX(gset)][gcode] = strpool(str); } fprintf(mfp, "\n", uni, ehigh, elow); fprintf(ffp, "\n", ehigh, elow, uni); for (i = 0; i < 16; i++) { if ((p = fgets(buf, MAX_GLINE, fp)) == NULL) break; for (j = 0; j < 8; j++) { if (*p == '@') putc('#', ffp); else putc(' ', ffp); if (*p) p++; } fprintf(ffp, "\n"); } for (; i < 16; i++) fprintf(ffp, " \n"); fprintf(ffp, "\n"); if (++elow > 0x7e) { elow = 0x21; ehigh++; } if (p != NULL) p = fgets(buf, MAX_GLINE, fp); } fprintf(ffp, "\n"); rewind(fp); elow = 0x21; ehigh++; fprintf(ffp, "\n", ehigh, elow); p = fgets(buf, MAX_GLINE, fp); while (p != NULL) { if (strncmp(p, "CHAR:", 5)) { p = fgets(buf, MAX_GLINE, fp); continue; } p = getupto(p+5, name, ':') + 1; if (*p == '"') { p = fgets(buf, MAX_GLINE, fp); continue; } if (sscanf(name, "G%d-%x", &gset, &gcode) == 2 && GIDX(gset) != -1 && gcode >= 0x00 && gcode <= 0xff) { issp = FALSE; } else { issp = TRUE; } if (*p != 'Z') { p = fgets(buf, MAX_GLINE, fp); continue; } if (isdigit(p[1])) times = atoi(p+1); else times = 1; if (times <= 1) { p = skipch(p, ':'); if (!strncmp(p, "U+", 2)) getupto(p+2, uni, ':'); else sprintf(uni, "%04X", unino++); sprintf(str, "&#x%s;", uni); if (issp) { gsp = (GSP *)malloc(sizeof(GSP)); gsp->name = strpool(name); gsp->str = strpool(str); gsp->next = gsptop; gsptop = gsp; } else { gtable[GIDX(gset)][gcode] = strpool(str); } fprintf(mfp, "\n", uni, ehigh, elow); fprintf(ffp, "\n", ehigh, elow, uni); for (i = 0; i < 16; i++) { if ((p = fgets(buf, MAX_GLINE, fp)) == NULL) break; for (j = 0; j < 16; j++) { if (*p == '@') putc('#', ffp); else putc(' ', ffp); if (*p) p++; } fprintf(ffp, "\n"); } for (; i < 16; i++) fprintf(ffp, " \n"); fprintf(ffp, "\n"); if (++elow > 0x7e) { elow = 0x21; ehigh++; } if (p != NULL) p = fgets(buf, MAX_GLINE, fp); continue; } q = addstr(str, ""); for (n = 0; n < times; n++) { sprintf(q, "&#x%04X;", unino + n); q = endstr(q); } q = addstr(q, ""); *q = '\0'; if (issp) { gsp = (GSP *)malloc(sizeof(GSP)); gsp->name = strpool(name); gsp->str = strpool(str); gsp->next = gsptop; gsptop = gsp; } else { gtable[GIDX(gset)][gcode] = strpool(str); } fgetpos(fp, &pos); for (n = 0; n < times; n++) { if (n > 0) fsetpos(fp, &pos); fprintf(mfp, "\n", unino+n, ehigh, elow); fprintf(ffp, "\n", ehigh, elow, unino+n); for (i = 0; i < 16; i++) { if ((p = fgets(buf, MAX_GLINE, fp)) == NULL) break; for (j = 0; j < n * 16; j++) { if (*p) p++; } for (j = 0; j < 16; j++) { if (*p == '@') putc('#', ffp); else putc(' ', ffp); if (*p) p++; } fprintf(ffp, "\n"); } for (; i < 16; i++) fprintf(ffp, " \n"); fprintf(ffp, "\n"); if (++elow > 0x7e) { elow = 0x21; ehigh++; } if (p == NULL) break; } unino += times; if (p != NULL) p = fgets(buf, MAX_GLINE, fp); } fclose(fp); fprintf(ffp, "\n"); fprintf(ffp, "\n"); fclose(ffp); fprintf(mfp, "\n"); fclose(mfp); for (n = 0; n <= 7; n++) { byte **gt; gt = gtable[n]; if (gt['<'] == NULL) gt['<'] = strpool("<"); if (gt['>'] == NULL) gt['>'] = strpool(">"); if (gt['&'] == NULL) gt['&'] = strpool("&"); if (gt['"'] == NULL) gt['"'] = strpool("""); if (gt['\''] == NULL) gt['\''] = strpool("'"); for (ch = 0; ch < 256; ch++) { if (gt[ch] != NULL) continue; if (ch >= 0x21 && ch <= 0x7e) { str[0] = ch; str[1] = '\0'; } else { sprintf(str, "{G%d-%02X}", (n <= 6)? n: 99, ch); } gt[ch] = strpool(str); } } message(" 終了しました\n"); return OK; } /* * 外字セットと外字番号から外字表記文字列を返す */ byte * gstr(int gset, int gcode) { int n; static byte buf[32]; if (gset == -1) { /* * タグ抜けがあった * 本文とみなす */ gset = 0; } if ((n = GIDX(gset)) != -1 && gcode >= 0x00 && gcode <= 0xff) return gtable[n][gcode]; sprintf(buf, "{G%d-%02X}", gset, gcode); return buf; } /* * 外字参照名から外字表記文字列を返す */ byte * gstrbyname(byte *name) { int n, gset, gcode; GSP *gsp; if (sscanf(name, "G%d-%x", &gset, &gcode) == 2 && (n = GIDX(gset)) != -1 && gcode >= 0x00 && gcode <= 0xff) return gtable[n][gcode]; for (gsp = gsptop; gsp != NULL; gsp = gsp->next) { if (!strcmp(name, gsp->name)) return gsp->str; } return name; } /* * 外字参照名を含む連結表記から文字列を組み立てる */ byte * buildstr(byte *buf, byte *str) { byte *p, *q; byte name[MAX_WORD]; p = str; q = buf; while (*p) { if (*p == '"') { p = getqword(q, p); q = endstr(q); } else { p = getuptos(p, name, " \""); q = addstr(q, gstrbyname(name)); p = skipsp(p); } } *q = '\0'; return buf; } /* -------------------- 書式処理 -------------------- */ /* * 本文データ行頭のラベル */ #define LBL_ERROR (-1) #define LBL_CMT 0 /* 注釈(非表示) */ #define LBL_DR 1 /* 派生形 */ #define LBL_EN 2 /* 見出し語 */ #define LBL_ENN 3 /* 検索用異表記???(非表示) */ #define LBL_ENV 4 /* 異表記 */ #define LBL_ENVN 5 /* 別綴り異表記??? */ #define LBL_ET 6 /* 初出??? */ #define LBL_EV 7 /* 同義語 */ #define LBL_EX 8 /* 用例 */ #define LBL_EXKEY 9 /* 用例検索キー */ #define LBL_EXSUB 10 /* 用例サブ項目 */ #define LBL_F 11 /* IFの誤記???(tallith) */ #define LBL_ID 12 /* 成句 */ #define LBL_IDSUB 13 /* 成句サブ項目 */ #define LBL_IF 14 /* 不規則活用 */ #define LBL_IMG 15 /* 図版データ(非表示) */ #define LBL_J2E 16 /* 日本語から借用(adsuki bean) */ #define LBL_KEY 17 /* 検索キー(非表示) */ #define LBL_KEYEX 18 /* 用例検索キー(非表示) */ #define LBL_KEYID 19 /* 成句検索キー(非表示) */ #define LBL_LOC 20 /* 本文格納位置(非表示) */ #define LBL_MEN 21 /* MNの誤記??? */ #define LBL_MN 22 /* 意味 */ #define LBL_MNSUB 23 /* 意味サブ項目 */ #define LBL_NB 24 /* 註 */ #define LBL_NBP 25 /* 表現註 */ #define LBL_NBPSUB 26 /* 表現註サブ項目 */ #define LBL_NBSUB 27 /* 註サブ項目 */ #define LBL_NSBUS 28 /* NBSUBの誤記???(and) */ #define LBL_OT1 29 /* 類語 */ #define LBL_OT1SUB 30 /* 類語サブ項目 */ #define LBL_OT2 31 /* 語法 */ #define LBL_OT2SUB 32 /* 語法サブ項目 */ #define LBL_OT3 33 /* 活用 */ #define LBL_OT3SUB 34 /* 活用サブ項目 */ #define LBL_OT4 35 /* 発音 */ #define LBL_OT4SUB 36 /* 発音サブ項目 */ #define LBL_OT5 37 /* 地域的異形 */ #define LBL_OT5SUB 38 /* 地域的異形サブ項目 */ #define LBL_PR 39 /* 発音 */ #define LBL_PS 40 /* 品詞 */ #define LBL_RA 41 /* ???(非表示) */ #define LBL_RES 42 /* ???(非表示) */ #define LBL_RN 43 /* ???(非表示) */ #define LBL_SM 44 /* ???(非表示) */ #define LBL_SND 45 /* 音声データ(非表示) */ #define LBL_SRC 46 /* 語源 */ #define LBL_SRCSUB 47 /* 語源サブ項目 */ #define LBL_TL 48 /* 文献タイトル */ #define LBL_TLSUB 49 /* 文献タイトルサブ項目 */ #define LBL_TQ 50 /* 意味分類(getの「I 所有する」)*/ #define LBL_TR 51 /* 語意 */ #define LBL_TRSUB 52 /* 語意サブ項目 */ typedef struct lbltbl_t { int id; /* ラベル識別ID */ int disp; /* 出力するか? */ byte *label; /* ラベル文字列 */ int tr; /* 語意番号(TRのとき) */ int trsub; /* 語意サブ番号(TRSUBのとき) */ } LBLTBL; /* * ラベル表 */ LBLTBL labeltbl[] = { { LBL_CMT, FALSE, "CMT" }, { LBL_DR, TRUE, "DR" }, { LBL_EN, TRUE, "EN" }, { LBL_ENN, FALSE, "ENN" }, { LBL_ENV, TRUE, "ENV" }, { LBL_ENVN, TRUE, "ENVN" }, { LBL_ET, TRUE, "ET" }, { LBL_EV, TRUE, "EV" }, { LBL_EX, TRUE, "EX" }, { LBL_EXKEY, FALSE, "EXKEY" }, { LBL_EXSUB, TRUE, "EXSUB" }, { LBL_F, TRUE, "F" }, { LBL_ID, TRUE, "ID" }, { LBL_IDSUB, TRUE, "IDSUB" }, { LBL_IF, TRUE, "IF" }, { LBL_IMG, TRUE, "IMG" }, { LBL_J2E, TRUE, "J2E" }, { LBL_KEY, FALSE, "KEY" }, { LBL_KEYEX, FALSE, "KEYEX" }, { LBL_KEYID, FALSE, "KEYID" }, { LBL_LOC, FALSE, "LOC" }, { LBL_MEN, TRUE, "MEN" }, { LBL_MN, TRUE, "MN" }, { LBL_MNSUB, TRUE, "MNSUB" }, { LBL_NB, TRUE, "NB" }, { LBL_NBP, TRUE, "NBP" }, { LBL_NBPSUB, TRUE, "NBPSUB" }, { LBL_NBSUB, TRUE, "NBSUB" }, { LBL_NSBUS, TRUE, "NSBUS" }, { LBL_OT1, TRUE, "OT1" }, { LBL_OT1SUB, TRUE, "OT1SUB" }, { LBL_OT2, TRUE, "OT2" }, { LBL_OT2SUB, TRUE, "OT2SUB" }, { LBL_OT3, TRUE, "OT3" }, { LBL_OT3SUB, TRUE, "OT3SUB" }, { LBL_OT4, TRUE, "OT4" }, { LBL_OT4SUB, TRUE, "OT4SUB" }, { LBL_OT5, TRUE, "OT5" }, { LBL_OT5SUB, TRUE, "OT5SUB" }, { LBL_PR, TRUE, "PR" }, { LBL_PS, TRUE, "PS" }, { LBL_RA, FALSE, "RA" }, { LBL_RES, FALSE, "RES" }, { LBL_RN, FALSE, "RN" }, { LBL_SM, FALSE, "SM" }, { LBL_SND, FALSE, "SND" }, { LBL_SRC, TRUE, "SRC" }, { LBL_SRCSUB, TRUE, "SRCSUB" }, { LBL_TL, TRUE, "TL" }, { LBL_TLSUB, TRUE, "TLSUB" }, { LBL_TQ, TRUE, "TQ" }, { LBL_TR, TRUE, "TR" }, { LBL_TRSUB, TRUE, "TRSUB" }, { LBL_ERROR, FALSE, NULL } }; LBLTBL *get_label(byte *); /* * 行頭のラベルを識別する */ LBLTBL * get_label(byte *str) { byte *p, *q; byte tmp[MAX_WORD]; LBLTBL *lp; if (!strncmp(str, "OT", 2)) { strncpy(tmp, str, 3); tmp[3] = '\0'; } else if (!strncmp(str, "J2E", 3)) { strcpy(tmp, "J2E"); } else { p = str; q = tmp; while (*p && isalpha(*p) && isupper(*p)) *q++ = *p++; *q = '\0'; } lp = labeltbl; while (lp->label != NULL) { if (!strncmp(tmp, lp->label, strlen(tmp))) break; lp++; } if (lp->id == LBL_OT1 || lp->id == LBL_OT2 || lp->id == LBL_OT3 || lp->id == LBL_OT4 || lp->id == LBL_OT5) { if (isdigit(str[2]) && str[3] == 'S') lp++; /* OTnの代わりにOTnSUBを指すようにする */ } else if (lp->id == LBL_TR) { lp->tr = atoi(str+2); } else if (lp->id == LBL_TRSUB) { lp->tr = atoi(str+5); lp->trsub = atoi(skipch(str+5, '(')); } return lp; } /* -------------------- メイン -------------------- */ #define MAIN_FILE "main.txt" /* 本文ファイル */ #define EN_FILE "en.dat" /* 英語索引語リスト */ #define TR_FILE "tr.dat" /* 日本語索引語リスト */ #define README_FILE "Readme.txt" /* 著作権表示 */ #define IMG_FILE "img.dat" /* 図版データ */ #define WIN_SND_FILE "srdra.bnd" /* 音声データ(Windows版) */ #define MAC_SND_FILE "srdq3.bnd" /* 音声データ(Macintosh版) */ #define INI_FILE "srd2html.ini" /* 設定ファイル */ #define GTBL_FILE "srdgaiji.tbl" /* 外字データファイル */ #define QJD_FILE "quickjmp.dat" /* 項目内ジャンプデータファイル */ #define HLT_FILE "hyperlnk.tmp" /* ハイパーリンク作業ファイル */ #define HLD_FILE "hyperlnk.dat" /* ハイパーリンクデータファイル */ #define HTML_FILE "srd.html" /* 出力HTMLファイル */ #define MENU1_FILE "srdmenu1.html" /* メニューファイル1(図版) */ #define MENU2_FILE "srdmenu2.html" /* メニューファイル2(作品名) */ #define MENU3_FILE "srdmenu3.html" /* メニューファイル3(類語) */ #define MENU4_FILE "srdmenu4.html" /* メニューファイル4(語法) */ #define MENU5_FILE "srdmenu5.html" /* メニューファイル5(活用他) */ #define COPR_FILE "srdcopr.html" /* 著作権表示ファイル */ #define CMPL_FILE "srdcmpl.xml" /* 複合検索定義ファイル */ #define GFONT_FILE "srdgfont.xml" /* 外字フォントファイル */ #define GMAP_FILE "srdgmap.xml" /* 外字マップファイル */ #define EBS_FILE "srd.ebs" /* EBStudio定義ファイル */ #define FIG_DIR "fig" /* 図版データ出力ディレクトリ名 */ #define SND_DIR "snd" /* 音声データ出力ディレクトリ名 */ #define MAX_LINE 4096 /* 入力行バッファのサイズ */ /* Ver.1.1のmain.datの最大行長 */ /* 2389だが余裕をみておく */ #define MAX_HLDATA 200 /* 1項目内のHLアンカー最大数 */ /* Ver.1.1で170だが余裕をみる */ #define MAX_HOLD 65536 /* 出力保持バッファのサイズ */ #define HOLD_MARGIN 4096 /* 〃の空きが4096を切ったら警告 */ #define QJ_NONE 0 /* 項目内ジャンプなし */ #define QJ_INLINE 1 /* 〃見出し行に表示 */ #define QJ_NEXTLINE 2 /* 〃次行に1行で表示 */ #define QJ_NEXTNLINE 3 /* 〃次行から複数行で表示 */ #define QJ_INDIRECT 4 /* 〃専用ページに表示 */ #define ST_START 0 /* 読み込み前 */ #define ST_CONT 1 /* 読み込み途中 */ #define ST_END 2 /* ファイル末尾に達した */ typedef struct hldata_t { byte *itemno; /* 項目番号 */ byte tag[12]; /* ハイパーリンク飛び先タグ */ int id; /* ハイパーリンク飛び先ラベル */ byte *ps; /* 飛び先の品詞 */ int tr; /* 飛び先の語意番号 */ int trsub; /* 飛び先の語意サブ番号 */ byte *str; /* 飛び先の派生形または成句 */ byte *cstr; /* strから空白/#nn#を除いたもの */ int done; /* アンカー書き込み済み */ } HLDATA; HLDATA hldata[MAX_HLDATA]; /* 1項目内のHLアンカー */ byte *pslist[] = { "adj.", "adv.", "auxil.v.", "conj.", "interj.", "n.", "prep.", "pron.", "v.", "v.i.", "v.t.", NULL }; char *base_path = ""; /* EBStudio基準ディレクトリ */ char *out_path = ""; /* EBSdudio出力先 */ char *dic_path = ""; /* 辞書ファイルの場所 */ char *data_path = ""; /* マルチメディアファイルの場所 */ char *sort_cmd = ""; /* ソートコマンドのパス */ int macintosh = 0; /* Macintosh版ランダムハウスか? */ int do_figure = 1; /* 図版データを使用するか? */ int use_jpeg = 1; /* 図版データをJPEGにするか? */ int do_sound = 0; /* 音声データを使用するか? */ int generate_sound = 1; /* 音声データファイルを生成? */ int do_complexed_index = 1; /* 成句・用例の複合検索? */ int do_quickjump = 0; /* 項目内ジャンプを使用するか? */ int qj_items = 3; /* 〜項目以上ならジャンプを生成 */ int qj_lines = 30; /* 〜行以上ならジャンプを生成 */ int do_quickret = 0; /* 戻りジャンプを使用するか? */ int use_italic = 0; /* イタリックを斜体で表記する? */ byte *pron_sym = "→発音"; /* 発音リンク */ byte *jump_sym = "→品詞"; /* 項目内間接ジャンプ */ byte *arrow_sym = "→"; /* 項目内ジャンプ矢印 */ byte *ret_sym = "↑"; /* リターンリンク */ char *figure_path = ""; /* 図版データ出力ディレクトリ */ char *sound_path = ""; /* 音声データ出力ディレクトリ */ char *sound_path_slash = ""; /* "/"区切りのsound_path */ int hlno; /* ハイパーリンク順序番号 */ time_t start_time; /* 開始時刻 */ time_t stop_time; /* 終了時刻 */ int init_gaiji(void); void reset_hlno(void); int next_hlno(void); byte *decode_hl_address(byte *, byte *, byte *, int); int generate_hyperlink_file(void); byte *conv_hyperlink(byte *, byte **, byte *, int); int conv_html(byte *, byte *, byte *, byte *, int); int conv_title(byte *, byte *); int conv_example(byte *, byte *); int generate_quickjump_file(void); byte *hl_canonical(byte *, byte *); byte *hl_getentry(FILE *); void hl_generate_anchor(byte *, int, byte *, int, int, byte *); void hl_warn_undone(void); int hl_flush_anchor(FILE *, int *); byte *indentstr(int); int do_convert(void); int generate_copyright_file(void); int generate_complex_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 **); /* * 外字表の初期化と変換を行う */ int init_gaiji(void) { if (process_gaiji(base_path, GTBL_FILE, GMAP_FILE, GFONT_FILE) == ERR) return ERR; return OK; } /* * ハイパーリンク順序番号をリセットする */ void reset_hlno(void) { hlno = 0; } /* * 次のハイパーリンク順序番号を取り出す */ int next_hlno(void) { return ++hlno; } /* * ハイパーリンクのアドレス表記をデコードする */ byte * decode_hl_address(byte *src, byte *target, byte *key, int dolog) { byte *p, *id, *ps; byte **pp; byte tr[MAX_WORD], trsub[MAX_WORD], str[MAX_WORD]; byte tmp[MAX_DLINE]; static byte buf[MAX_DLINE]; /* * "要素:要素:要素"から"ID:PS:TR:TRSUB:STR"を作って返す * IDはのトリガーとなるラベル、ほかは制約条件 * * 例) * DR:"appointer":null ID=DR, STR="appointer" * v.t.:null:null ID=PS, PS=v.t. * adj.:1-3:null ID=TR, PS=adj., TR=1 * adj.:4,5:null ID=TR, PS=adj., TR=4 * v.t.:(1):null ID=TR, PS=v.t., TR=1 * null:1:null ID=TR, PS=(n/a), TR=1 * adj.:1:2 ID=TRSUB, PS=adj., TR=1, TRSUB=2 * n.:5:(1) ID=TRSUB, PS=n., TR=5, TRSUB=1 * n.:8(1):null ID=TRSUB, PS=n., TR=8, TRSUB=1 * null:1:2 ID=TRSUB, PS=(n/a), TR=1, TRSUB=2 * v.i.:"flake out":null ID=KEYID, PS=v.i., STR="flake out" * n.:成句:null ID=KEYID, PS=n., STR=(n/a) * null:"look in":1 ID=KEYID, PS=(n/a), STR="look in" * null:"as well":null ID=KEYID, PS=(n/a), STR="as well" * null:成句:null ID=KEYID, PS=(n/a), STR=(n/a) * adj.:15:【類語】 ID=OT1, PS=adj., TR=15 * n.:【類語】:null ID=OT1, PS=n., TR=(n/a) * null:2:【類語】 ID=OT1, PS=(n/a), TR=2 * null:1:【語法】(4) ID=OT2, PS=(n/a), TR=1 * null:【類語】:"go" ID=OT1, PS=(n/a), TR=(n/a) * null:【語法】:1 ID=OT2, PS=(n/a), TR=(n/a) * null:【語法】:null ID=OT2, PS=(n/a), TR=(n/a) * null:1:(用例) ID=KEYEX, PS=(n/a), TR=1 * null:用例:null ID=KEYEX, PS=(n/a), TR=(n/a) * null:◇:null ID=TL, PS=(n/a) * null:◇:[文学] ID=TLSUB, PS=(n/a), STR="[文学]" * n.:図:null ID=IMG, PS=n. * null:図:null ID=IMG, PS=(n/a) * null:語源:null ID=SRC, PS=(n/a) * null:null:null NULL * * 読み替える) * PS:N:(M) n.:5:(1) → PS:N:M * PS:N(M):null n.:8(1):null → PS:N:M * PS:(N):null v.t.:(1):null → PS:N:null * N:null:null → null:N:null * S:null:null → null:S:null * N:OTn:null → null:N:OTn * OTn:S:null 【類語】:"frequently":null → null:OTn:S * OTn:null:null → null:OTn:null * * 対応しない) * null:XXX:N null:the:2 → NULL * null:XXX:null null:as a sudge:null → NULL * null:XXX:null null:time 成句:null → NULL * null:XXX:null null:v. 成句:null → NULL */ if (!isdigit(*target)) { /* * 項目番号が不正 */ if (dolog) { getupto(src, buf, '<'); write_log("飛び先不明のハイパーリンク「%s:%s」があります(%s)\n", target, buf, key); } return NULL; } if (!strncmp(src, "null:null:null", 14)) { /* * 飛び先は項目先頭 */ return NULL; } id = ps = NULL; *tr = *trsub = *str = '\0'; p = src; getupto(p, tmp, ':'); if (!strcmp(tmp, "DR")) { /* * 先頭がDRなら必ず DR:"sss":xxx の形 */ p = skipch(p, ':'); getqword(p, tmp); sprintf(buf, "DR::::%s", tmp); return buf; } /* * 先頭要素のチェック */ ps = ""; for (pp = pslist; *pp; pp++) { if (!strcmp(tmp, *pp)) { id = "PS"; ps = *pp; break; } } if (id || !strncmp(tmp, "nul", 3)) { /* * nullと比較しないのは nul:3:null というバグデータがあるため * 先頭のnullは省略されることがあるので、品詞でもnull(nul)でも * ない場合は読み飛ばさない */ p = skipch(p, ':'); } /* * 第2要素のチェック */ if (*p == '(') { /* * xxx:(1):yyy の形 */ p++; } if (isdigit(*p)) { /* * TRが指定された * (null:30-dash:null というバグデータがあるが無視) */ id = "TR"; p = getnumber(p, tr); if (*p == '(' && isdigit(p[1])) { /* * TRSUBが指定された * xxx:8(1):yyy の形 */ id = "TRSUB"; p = getnumber(p+1, trsub); } p = skipch(p, ':'); /* * 第2要素がTRのとき→第3要素のチェック */ if (*p == '(') { /* * xxx:yyy:(3) か xxx:yyy:(用例) の形 */ p++; } if (isdigit(*p)) { /* * TRSUBが指定された * xxx:yyy:4 または xxx:yyy:(2) の形 */ id = "TRSUB"; p = getnumber(p, trsub); } else if (!strncmp(p, "【類語】", 8)) { id = "OT1"; } else if (!strncmp(p, "【語法】", 8)) { id = "OT2"; } else if (!strncmp(p, "【活用】", 8)) { id = "OT3"; } else if (!strncmp(p, "【発音】", 8)) { id = "OT4"; } else if (!strncmp(p, "【地域的異形】", 14)) { id = "OT5"; } else if (!strncmp(p, "用例", 4)) { id = "KEYEX"; } } else if (*p == '"' || !strncmp(p, "成句", 4)) { /* * xxx:"sss":null または xxx:成句:null の形 */ id = "KEYID"; if (*p == '"') { p = getqword(p, str); /* * タグが含まれていることがある */ removetag(str); } } else if (!strncmp(p, "【類語】", 8)) { id = "OT1"; } else if (!strncmp(p, "【語法】", 8)) { id = "OT2"; } else if (!strncmp(p, "【活用】", 8)) { id = "OT3"; } else if (!strncmp(p, "【発音】", 8)) { id = "OT4"; } else if (!strncmp(p, "【地域的異形】", 8)) { id = "OT5"; } else if (!strncmp(p, "◇", 2)) { id = "TL"; p = skipch(p, ':'); if (*p == '[') { /* * xxx:◇:[文学] の形 */ id = "TLSUB"; p = getupto(p, str, ']'); strcat(str, "]"); } } else if (!strncmp(p, "用例", 4)) { id = "KEYEX"; } else if (!strncmp(p, "図", 2)) { id = "IMG"; } else if (!strncmp(p, "語源", 4)) { id = "SRC"; } if (id == NULL) { /* * 飛び先不明... */ if (dolog) { getupto(src, buf, '<'); write_log("解決不能なハイパーリンク「%s」があります(%s)\n", buf, key); } return NULL; } sprintf(buf, "%s:%s:%s:%s:%s", id, ps, tr, trsub, str); return buf; } /* * ハイパーリンクデータファイルを生成する(Pass1) */ int generate_hyperlink_file(void) { long lpos, base, pc, prevpc; byte *p, *q, *srctop, *addr; byte itemno[MAX_WORD], key[MAX_WORD], target[MAX_WORD]; byte linebuf[MAX_LINE], buf[MAX_DLINE]; FILE *mainfp, *hlfp; LBLTBL *lp; message("ハイパーリンクデータを生成しています..."); write_log("\n"); if ((mainfp = dic_open(dic_path, MAIN_FILE)) == NULL || (hlfp = hl_newfile(HLT_FILE)) == NULL) { return ERR; } base = dic_filesize() / 100L; prevpc = -1; reset_hlno(); while (dic_getline(mainfp, linebuf) != NULL) { lp = get_label(linebuf); p = skipch(linebuf, '='); switch (lp->id) { case LBL_RA: /* 項目開始 */ lpos = dic_linepos(); pc = lpos / base; if (pc > prevpc) { printf("\rハイパーリンクデータを生成しています... %ld%%", pc); fflush(stdout); prevpc = pc; } break; case LBL_RN: /* 項目番号 */ strcpy(itemno, p); break; case LBL_EN: /* 項目見出し */ p = skipch(p, '|'); strcpy(key, p); break; case LBL_EX: /* 用例 */ if (do_complexed_index && (q = strstr(p, " ")) != NULL) { /* * 複合検索が有効かつ用例にがある場合、 * 以降のみについてハイパーリンクを作る * do_convert()のLBL_EXと一致させておくこと */ p = q; } goto output; default: output: if (!lp->disp) break; srctop = p; while (*p) { if (*p != '<') { p++; continue; } if (!strncmp(p, "", 5)) { byte *q; /* * まで読み捨てる */ if ((q = strstr(p, "")) != NULL) p = q + 6; else p++; continue; } if (strncmp(p, "", 4) && strncmp(p, "", 5)) { p++; continue; } if (!strncmp(p, "", 5)) { /* * 開きタグの脱落 * 必要なところまで後戻りする */ while (p > srctop && strncmp(p, "", 4)) p--; } while (*p && *p != ':') { if (*p & 0x80) p++; p++; } if (!*p) break; p = getupto(p+1, target, ':') + 1; target[8] = '\0'; /* "14152700.5:null:5:null"というバグデータへの対処 */ if (!strcmp(target, "0")) { /* * 飛び先は同じ項目内 */ strcpy(target, itemno); } if ((addr = decode_hl_address(p, target, key, TRUE)) != NULL) { /* * 飛び先が項目先頭ではなかったので * ハイパーリンクデータを生成する */ p = getupto(p, buf, '<'); fprintf(hlfp, "%8s|HL%06d|%s|%s|%s|(%s)\n", target, next_hlno(), addr, itemno, key, buf); } if ((p = strstr(p, "")) == NULL) break; p += 5; /* をスキップ */ srctop = p; /* これ以上戻らない */ } break; } } dic_close(mainfp); hl_close(hlfp); printf("\rハイパーリンクデータを生成しています... "); message("終了しました\n"); message("ハイパーリンクデータをソートしています..."); sprintf(buf, "%s %s > %s", sort_cmd, HLT_FILE, HLD_FILE); system(buf); message(" 終了しました\n"); return OK; } /* * ハイパーリンクタグを解決する(Pass2) */ byte * conv_hyperlink(byte *dst, byte **srcp, byte *itemno, int genjump) { byte *p, *addr; byte target[MAX_WORD], buf[MAX_LINE]; #ifdef DEBUG int n; FILE *fp; #endif p = *srcp; while (*p && *p != ':') { if (*p & 0x80) p++; p++; } *p = '\0'; conv_html(buf, *srcp, itemno, "", FALSE); *p = ':'; p = getupto(p+1, target, ':') + 1; target[8] = '\0'; if (!strcmp(target, "0")) { /* * 飛び先は現在の項目内 */ strcpy(target, itemno); } addr = decode_hl_address(p, target, "", FALSE); p = strstr(p, ""); if (p) p += 5; /* を読み飛ばす*/ *srcp = p; if (!genjump) { /* * ジャンプを生成しない(メニュー内など) */ sprintf(dst, "%s", buf); } else if (addr != NULL) { /* * 飛び先が項目先頭ではなかった * ハイパーリンクタグへのジャンプを生成する * next_hlno()はPass1と同じ値を生成しなければならない */ #ifdef DEBUG n = next_hlno(); sprintf(dst, "%s", n, buf); fp = fopen("pass2.tmp", "a"); fprintf(fp, "%8s|HL%06d|%s|%s\n", target, n, addr, itemno); fclose(fp); #else sprintf(dst, "%s", next_hlno(), buf); #endif } else { /* * 項目先頭へのジャンプを生成する */ sprintf(dst, "%s", target, buf); } while (*dst) dst++; return dst; } /* * 本文1行についてHTMLへのタグ変換、外字変換などを行う */ int conv_html(byte *dst, byte *src, byte *itemno, byte *srchkey, int genjump) { int gset; byte *p, *srctop, *dsttop, tag[MAX_WORD]; gset = -1; srctop = src; dsttop = dst; p = src; while (*p) { if (*p == 0xa5) { /* * 本文中の1バイト中点は * 2バイト中点に変換する */ dst = addstr(dst, "・"); p++; } else if (*p == '&') { dst = addstr(dst, "&"); p++; } else if (*p == '"') { dst = addstr(dst, """); p++; } else if (*p == '\'') { dst = addstr(dst, "'"); p++; } else if (*p == '#' && p[3] == '#') { /* * #nn#: 外字またはエスケープ表記 */ dst = addstr(dst, gstr(gset, hexval(p+1))); p += 4; } else if (*p == '>') { dst = addstr(dst, ">"); p++; } else if (*p == '<' && p[1] == '/') { /* * 終了タグの処理 */ p = getupto(p+2, tag, '>') + 1; if (*tag == 'G') { gset = -1; } else if (!strcmp(tag, "B")) { /* 太字 */ dst = addstr(dst, ""); } else if (!strcmp(tag, "I") || !strcmp(tag, "SPO")) { /* 斜体 */ if (use_italic) dst = addstr(dst, ""); } else if (!strcmp(tag, "SUP")) { dst = addstr(dst, ""); } else if (!strcmp(tag, "SUB")) { dst = addstr(dst, ""); } else if (!strcmp(tag, "RUBY")) { *dst++ = ')'; } else if (!strcmp(tag, "HL")) { /* * 開きタグの脱落 * V1.1には次の4箇所ある * behind: #88#BE- * :1540300:null:null:null * foreword: cf. AFTERWORD * :298800:null:null:null * humus: #88#HOMO * :8216900:null:null:null * Reconstructionist: #89#R * ECONSTRUCTIONISM * :14474100:null:null:null * これに対処するため、変換元はまで、 * 変換先は"&"あるいは"."、","、" "の直後まで戻り、 * そこにがあったことにして処理を再開する */ write_log("本文に誤りがあります\n"); write_log(" ERR: の脱落\n"); write_log(" KEY: %s\n", srchkey); write_log(" LINE: %s\n", src); while (p > srctop && strncmp(p, "", 4)) p--; while (dst > dsttop && *dst != '&' && *dst != '.' && *dst != ',' && *dst != ' ') dst--; if (p == srctop || dst == dsttop) { write_log(" 上記エラーへの対処に失敗しました\n"); write_log(" 変換結果に脱落があります\n"); printf("項目 %s で変換に失敗しました\n"); } else write_log(" 上記エラーへの対処に成功しました\n"); if (*dst != '&') dst++; dst = conv_hyperlink(dst, &p, itemno, genjump); } else { /* * 上記以外のタグは読み捨てる * ただし未知のタグはログに記録 */ if (strcmp(tag, "SO") && strcmp(tag, "SC") && strcmp(tag, "OBJ") && strcmp(tag, "DSR") && strcmp(tag, "FONT")) { write_log("本文に未知のタグがあります\n"); write_log(" TAG: \n", tag); write_log(" KEY: %s\n", srchkey); write_log(" LINE: %s\n", srctop); } } } else if (*p == '<' && p[1] == '<') { dst = addstr(dst, "<"); p++; } else if (*p == '<') { /* * 開始タグの処理 */ p = getupto(p+1, tag, '>') + 1; if (*tag == 'G') { if (tag[1] == '9') gset = 99; else gset = tag[1] - '0'; } else if (!strcmp(tag, "B")) { dst = addstr(dst, ""); } else if (!strcmp(tag, "I") || !strcmp(tag, "SPO")) { if (use_italic) dst = addstr(dst, ""); } else if (!strcmp(tag, "SUP")) { dst = addstr(dst, ""); } else if (!strcmp(tag, "SUB")) { dst = addstr(dst, ""); } else if (!strcmp(tag, "RUBY")) { *dst++ = '('; } else if (!strcmp(tag, "HL")) { dst = conv_hyperlink(dst, &p, itemno, genjump); } else if (!strcmp(tag, "CMT")) { byte *q; /* * まで読み捨てる */ if ((q = strstr(p, "")) != NULL) p = q + 6; } else { /* * 上記以外のタグは読み捨てる * ただし未知のタグはログに記録 */ if (strcmp(tag, "SO") && strcmp(tag, "SC") && strcmp(tag, "OBJ") && strcmp(tag, "DSR") && strncmp(tag, "FONT ", 5)) { write_log("本文に未知のタグがあります\n"); write_log(" TAG: \n", tag); write_log(" KEY: %s\n", srchkey); write_log(" LINE: %s\n", srctop); } } } else if (*p & 0x80) { /* * 2バイト漢字 */ *dst++ = *p++; *dst++ = *p++; } else if (gset == 5 && *p >= 'A') { /* * G5セットでは通常文字もSmall Capitalにする */ dst = addstr(dst, gstr(gset, *p++)); } else { /* * 通常の1バイト文字 */ *dst++ = *p++; } } *dst = '\0'; return OK; } /* * 見出し文字列のタグ除去、外字変換を行う */ int conv_title(byte *dst, byte *src) { byte *p; static byte cdot[9] = ""; if (!*cdot) { /* * 最初の1回だけcdotの準備 */ strcpy(cdot, gstr(99, 0xa5)); } p = src; while (*p) { if (*p == 0xa5) { /* * 1バイト中点 * cdot(外字セットG99の0xa5)に変換する */ dst = addstr(dst, cdot); p++; } else if (*p == '#' && p[3] == '#') { /* * #nn#: 外字またはエスケープ表記 * (見出しの外字はすべてG99セット) */ dst = addstr(dst, gstr(99, hexval(p+1))); p += 4; } else if (*p == '<') { /* * タグはすべて読み捨てる * , , * , がある */ p = skipch(p, '>'); } else { *dst++ = *p++; } } *dst = '\0'; return OK; } /* * 用例本体のタグ除去、外字変換を行う */ int conv_example(byte *dst, byte *src) { int gset; byte *p, tag[MAX_WORD]; gset = -1; p = src; while (*p) { if (*p == 0xa5) { /* * 用例中の1バイト中点は * 2バイト中点に変換する */ dst = addstr(dst, "・"); p++; } else if (*p == '#' && p[3] == '#') { /* * #nn#: 外字またはエスケープ表記 */ dst = addstr(dst, gstr(gset, hexval(p+1))); p += 4; } else if (*p == '<') { /* * 外字以外のタグはすべて読み捨てる */ p = getupto(p+1, tag, '>') + 1; if (*tag == 'G') { if (tag[1] == '9') gset = 99; else gset = tag[1] - '0'; } } else { *dst++ = *p++; } } *dst = '\0'; return OK; } /* * 項目内ジャンプデータファイルを生成する */ int generate_quickjump_file(void) { int newidiom, pscount, idcount, lines; long lpos, base, pc, prevpc; byte *p; byte itemno[MAX_WORD], key[MAX_WORD]; byte name[MAX_WORD], tmp[MAX_WORD]; byte linebuf[MAX_LINE], buf[MAX_LINE]; FILE *mainfp, *qjfp; LBLTBL *lp; message("項目内ジャンプデータを生成しています..."); write_log("\n"); if ((mainfp = dic_open(dic_path, MAIN_FILE)) == NULL || (qjfp = qj_newfile(QJD_FILE)) == NULL) { return ERR; } base = dic_filesize() / 100L; prevpc = -1; pscount = 0; idcount = 0; lines = 0; newidiom = TRUE; *buf = '\0'; while (dic_getline(mainfp, linebuf) != NULL) { lp = get_label(linebuf); p = skipch(linebuf, '='); switch (lp->id) { case LBL_RA: /* 項目開始 */ if (pscount + idcount >= qj_items && lines >= qj_lines) { /* * 品詞/成句がqj_items以上、項目行数がqj_lines以上なら * 項目内ジャンプのためのリンクデータを生成する */ fprintf(qjfp, "%ld|%s|%s|%s\n", lpos, itemno, key, buf); } pscount = 0; idcount = 0; lines = 0; newidiom = TRUE; *buf = '\0'; lpos = dic_linepos(); pc = lpos / base; if (pc > prevpc) { printf("\r項目内ジャンプデータを生成しています... %ld%%", pc); fflush(stdout); prevpc = pc; } break; case LBL_RN: /* 項目番号 */ strcpy(itemno, p); break; case LBL_EN: /* 項目見出し */ p = skipch(p, '|'); strcpy(key, p); lines++; break; case LBL_DR: /* 派生形 */ strcat(buf, "派生形|"); lines++; break; case LBL_PS: /* 品詞 */ conv_html(tmp, p, itemno, "", FALSE); strcat(buf, tmp); strcat(buf, "|"); pscount++; newidiom = TRUE; /* 品詞の異なる成句は別に数える */ lines++; break; case LBL_ID: /* 成句 */ if (newidiom) { strcat(buf, "成句|"); idcount++; newidiom = FALSE; } lines++; break; case LBL_OT1: /* 類語 */ case LBL_OT2: /* 語法 */ case LBL_OT3: /* 活用 */ case LBL_OT4: /* 発音 */ case LBL_OT5: /* 地域的異形 */ p += 2; /* "【"をスキップ */ getuptow(p, name, "】"); strcat(buf, name); strcat(buf, "|"); lines++; break; default: if (lp->disp) lines++; break; } } if (pscount + idcount >= qj_items && lines >= qj_lines) fprintf(qjfp, "%ld|%s|%s|%s\n", lpos, itemno, key, buf); dic_close(mainfp); qj_close(qjfp); printf("\r項目内ジャンプデータを生成しています... "); message("終了しました\n"); return OK; } /* * 文字列から空白と"#nn#"を取り除く(成句キー比較用) */ byte * hl_canonical(byte *dst, byte *src) { byte *p, *q; p = src; q = dst; while (*p) { if (*p == ' ') { p++; continue; } if (*p == '#') { p += 4; continue; } if (*p & 0x80) *q++ = *p++; *q++ = *p++; } *q = '\0'; return dst; } /* * ハイパーリンクデータを1項目分読み込む */ byte * hl_getentry(FILE *fp) { byte *p, *s, **pp; HLDATA *hp; byte tmp[MAX_DLINE]; static int status = ST_START; static byte itemno[MAX_WORD], buf[MAX_DLINE], sbuf[MAX_LINE]; if (status == ST_END) return NULL; if (status == ST_START) { if (fgets(buf, MAX_DLINE, fp) == NULL) return NULL; status = ST_CONT; } hp = hldata; s = sbuf; p = skipsp(buf); p = getupto(p, itemno, '|') + 1; do { hp->itemno = itemno; /* 項目番号 */ p = getupto(p, hp->tag, '|') + 1; /* HLnnnnnn */ p = getupto(p, tmp, ':') + 1; /* 行頭ラベル */ hp->id = get_label(tmp)->id; p = getupto(p, tmp, ':') + 1; /* 品詞 */ hp->ps = NULL; for (pp = pslist; *pp; pp++) { if (!strcmp(tmp, *pp)) { hp->ps = *pp; break; } } p = getupto(p, tmp, ':') + 1; /* 語意番号 */ hp->tr = *tmp? atoi(tmp): -1; p = getupto(p, tmp, ':') + 1; /* 語意サブ番号 */ hp->trsub = *tmp? atoi(tmp): -1; p = getupto(p, tmp, '|') + 1; /* 派生形または成句 */ if (*tmp) { hp->str = s; s = addstr(s, tmp); *s++ = '\0'; hp->cstr = s; hl_canonical(s, tmp); s = endstr(s); s++; } else { hp->str = NULL; hp->cstr = NULL; } hp->done = FALSE; hp++; if (fgets(buf, MAX_DLINE, fp) == NULL) { status = ST_END; break; } status = ST_CONT; p = skipsp(buf); p = getupto(p, tmp, '|') + 1; } while (!strcmp(itemno, tmp)); hp->id = LBL_ERROR; return itemno; } /* * 条件を満たすアンカータグを生成する */ void hl_generate_anchor(byte *buf, int id, byte *ps, int tr, int trsub, byte *str) { byte *p, cstr[MAX_WORD]; HLDATA *hp; p = buf; for (hp = hldata; hp->id != LBL_ERROR; hp++) { if (hp->done) continue; if (hp->id != id) continue; if (hp->ps && (ps == NULL || strstr(ps, hp->ps) == NULL)) continue; if (hp->tr != -1 && (tr == -1 || hp->tr != tr)) continue; if (hp->trsub != -1 && (trsub == -1 || hp->trsub != trsub)) continue; if (hp->str) { if (str == NULL) continue; if (id == LBL_KEYID) { hl_canonical(cstr, str); if (strcmp(cstr, hp->cstr)) continue; } else { if (strcmp(str, hp->str)) continue; } } p = endstr(p); sprintf(p, "\n", hp->tag); hp->done = TRUE; } } /* * 生成されなかったハイパーリンクアンカーをログに書く */ void hl_warn_undone(void) { int first; HLDATA *hp; LBLTBL *lp; byte tr[10], trsub[10]; first = TRUE; for (hp = hldata; hp->id != LBL_ERROR; hp++) { if (hp->done) continue; for (lp = labeltbl; lp->id != hp->id; lp++) ; if (hp->tr < 0) *tr = '\0'; else sprintf(tr, "%d", hp->tr); if (hp->trsub < 0) *trsub = '\0'; else sprintf(trsub, "%d", hp->trsub); if (first) { write_log("飛び先不明のため項目末尾にハイパーリンクのアンカーを生成しました\n"); first = FALSE; } write_log(" 項目番号=%s, リンク=\"%s:%s:%s:%s:%s\"\n", hp->itemno, lp->label, hp->ps? hp->ps: "", tr, trsub, hp->str? hp->str: ""); } } /* * 残りのハイパーリンクアンカーを吐き出す */ int hl_flush_anchor(FILE *fp, int *needbrp) { int n; HLDATA *hp; n = 0; for (hp = hldata; hp->id != LBL_ERROR; hp++) { if (hp->done) continue; if (*needbrp) { fprintf(fp, "
\n"); *needbrp = FALSE; } fprintf(fp, "\n", hp->tag); hp->done = TRUE; n++; } return n; } /* * 字下げタグ文字列を作る */ byte * indentstr(int indent) { static byte buf[32]; sprintf(buf, "Ἁ�&#x%02x;", indent+1); return buf; } /* * 変換処理本体 */ int do_convert(void) { int n, hn, cnt; int qjno, newidiom, derived, needbr; int capital, figcap, figno, tlcap, tlno; int ot1cap, ot1no, ot2cap, ot2no, ot3cap, ot3no; int first, have_title, have_variant, have_pron, have_sound; int hlno_pass1, hlno_pass2, have_anchor, cur_tr, cur_trsub; int imgfd, sndfd; long lpos, dpos, dlen, qjpos, base, pc, prevpc, sndfiles; byte *p, *q, *qjp, *space, *indent, *hlitemno, *cur_ps; byte *snd_file, *fig_ext, *snd_ext; byte linebuf[MAX_LINE], htmlbuf[MAX_LINE]; byte qjbuf[MAX_DLINE], psbuf[MAX_DLINE]; byte itemno[MAX_WORD], drbuf[MAX_WORD]; byte title[MAX_WORD], variant[MAX_WORD], srchkey[MAX_WORD]; byte pron[MAX_WORD], key[MAX_WORD], soundref[MAX_WORD]; byte filename[MAX_WORD], tmp[MAX_WORD], snddir[4]; byte pron_ref[MAX_WORD], jump_ref[MAX_WORD]; byte arrow_ref[MAX_WORD], ret_ref[MAX_WORD]; FILE *fp, *mainfp, *enfp, *trfp, *qjfp, *hlfp; FILE *m1fp, *m2fp, *m3fp, *m4fp, *m5fp, *plfp, *plafp; LENT en, tr, *enp, *trp; LBLTBL *lp; static byte holdbuf[MAX_HOLD]; message("本文データをHTMLに変換しています..."); write_log("\n"); if (macintosh) { fig_ext = ".pict"; snd_ext = ".aifc"; snd_file = MAC_SND_FILE; } else { fig_ext = ".bmp"; snd_ext = ".ra"; snd_file = WIN_SND_FILE; } if ((mainfp = dic_open(dic_path, MAIN_FILE)) == NULL || (enfp = lst_open(dic_path, EN_FILE)) == NULL || (trfp = lst_open(dic_path, TR_FILE)) == NULL || do_quickjump && (qjfp = qj_open(QJD_FILE)) == NULL || (hlfp = hl_open(HLD_FILE)) == NULL || do_figure && (imgfd = dat_open(data_path, IMG_FILE)) < 0 || do_sound && (sndfd = dat_open(data_path, snd_file)) < 0 || (fp = html_newfile(base_path, HTML_FILE)) == NULL || do_figure && (m1fp = menu_newfile(base_path, MENU1_FILE, "図版")) == NULL || (m2fp = menu_newfile(base_path, MENU2_FILE, "作品名")) == NULL || (m3fp = menu_newfile(base_path, MENU3_FILE, "類語")) == NULL || (m4fp = menu_newfile(base_path, MENU4_FILE, "語法")) == NULL || (m5fp = menu_newfile(base_path, MENU5_FILE, "活用・発音・地域的異形")) == NULL) { return ERR; } base = dic_filesize() / 100L; prevpc = -1; enp = lst_getentry(enfp, &en); trp = lst_getentry(trfp, &tr); if (do_quickjump) qjpos = qj_getline(qjfp, qjbuf); first = TRUE; needbr = FALSE; *holdbuf = '\0'; sndfiles = 0L; plfp = NULL; figcap = tlcap = ot1cap = ot2cap = ot3cap = ' '; figno = tlno = ot1no = ot2no = ot3no = 0; hlno_pass1 = next_hlno() - 1; reset_hlno(); hlitemno = hl_getentry(hlfp); if (do_sound) buildstr(pron_ref, pron_sym); if (do_quickjump) { if (do_quickjump == QJ_INDIRECT) buildstr(jump_ref, jump_sym); buildstr(arrow_ref, arrow_sym); } buildstr(ret_ref, ret_sym); while (dic_getline(mainfp, linebuf) != NULL) { lp = get_label(linebuf); p = skipch(linebuf, '='); switch (lp->id) { case LBL_RA: /* 項目開始 */ lpos = dic_linepos(); have_title = FALSE; have_variant = FALSE; have_pron = FALSE; have_sound = FALSE; if (do_quickjump) { if (qjpos >= 0L && qjpos < lpos) qjpos = qj_getline(qjfp, qjbuf); if (qjpos == lpos) { qjp = skipch(qjbuf, '|'); /* ファイル位置をスキップ */ qjp = skipch(qjp, '|'); /* 項目番号をスキップ */ qjp = skipch(qjp, '|'); /* キーワードをスキップ */ qjno = 0; newidiom = TRUE; } else { qjp = NULL; } } have_anchor = FALSE; cur_ps = NULL; cur_tr = cur_trsub = -1; pc = lpos / base; if (pc > prevpc) { printf("\r本文データをHTMLに変換しています... %ld%%", pc); fflush(stdout); prevpc = pc; } break; case LBL_RN: /* 項目番号 */ strcpy(tmp, itemno); strcpy(itemno, p); if (hlitemno != NULL) { n = atoi(itemno); hn = atoi(hlitemno); cnt = 0; while (hn < n) { hl_warn_undone(); cnt += hl_flush_anchor(fp, &needbr); hlitemno = hl_getentry(hlfp); if (hlitemno == NULL) break; hn = atoi(hlitemno); } if (cnt > 0) { fprintf(fp, "%s%s", indentstr(1), tmp, ret_ref); needbr = TRUE; } have_anchor = (hlitemno && hn == n); } else { have_anchor = FALSE; } break; case LBL_EN: /* 項目見出し */ case LBL_DR: /* 派生形 */ p = getupto(p, tmp, '|'); strcpy(srchkey, p+1); conv_title(title, tmp); have_title = TRUE; if (lp->id == LBL_EN) derived = 0; else derived++; for (q = srchkey; *q; q++) { if (isalpha(*q)) break; } if (!*q) capital = '@'; else if (islower(*q)) capital = toupper(*q); else capital = *q; if (have_anchor && lp->id == LBL_DR) { hl_generate_anchor(holdbuf, LBL_DR, NULL, -1, -1, srchkey); } break; case LBL_ENV: /* 異表記 */ if (!have_title) goto output; conv_html(variant, p, itemno, "", TRUE); have_variant = TRUE; break; case LBL_PR: /* 発音 */ conv_html(pron, p, itemno, "", TRUE); have_pron = TRUE; break; case LBL_SND: /* 音声 */ if (!do_sound) break; sscanf(p, "%lx,%lx", &dpos, &dlen); if (dlen == 0L) break; if (sndfiles % 1000L == 0L) { sprintf(snddir, "%03ld", sndfiles / 1000); sprintf(tmp, "%s%s", sound_path_slash, snddir); if (generate_sound) mkdir(tmp); } if (macintosh && generate_sound && (sndfiles % 10000L == 0L)) { if (plfp != NULL) pl_close(plfp, sndfiles - 9999L, sndfiles); sprintf(tmp, "pl_%s.xml", snddir); if ((plfp = pl_newfile(base_path, tmp)) == NULL) return ERR; if (sndfiles == 0L) { if ((plafp = pl_newfile(base_path, "pl_all.xml")) == NULL) return ERR; } } filename[0] = snddir[0]; filename[1] = snddir[1]; filename[2] = snddir[2]; filename[3] = '/'; getupto(p, filename+4, ','); strcpy(tmp, filename); strcat(filename, snd_ext); if (generate_sound) { if (dat_splitfile(sound_path, filename, sndfd, dpos, dlen) == ERR) return ERR; if (macintosh) { if (pl_putentry(plfp, sound_path_slash, SND_DIR, snddir, dpos, sndfiles+1) == ERR || pl_putentry(plafp, sound_path_slash, SND_DIR, snddir, dpos, sndfiles+1) == ERR) { return ERR; } } } sprintf(soundref, "%s", SND_DIR, tmp, pron_ref); sndfiles++; have_sound = TRUE; break; case LBL_IMG: /* 図版 */ if (have_anchor) { hl_generate_anchor(holdbuf, LBL_IMG, cur_ps, cur_tr, cur_trsub, NULL); } if (!do_figure) break; sscanf(p, "%lx,%lx", &dpos, &dlen); getupto(p, filename, ','); strcpy(tmp, filename); strcat(tmp, fig_ext); if (dat_splitfile(figure_path, tmp, imgfd, dpos, dlen) == ERR) break; strcat(filename, use_jpeg? ".jpg": ".bmp"); if (capital != figcap) { if (figcap != ' ') fprintf(m1fp, "

\n"); fprintf(m1fp, "

%s

\n

\n", han2zen[capital]); figcap = capital; } fprintf(m1fp, "%s
\n", HTML_FILE, figno, title); sprintf(endstr(holdbuf), "\"%s\"", figno++, FIG_DIR, filename, title); goto output; case LBL_OT1: /* 類語 */ case LBL_OT2: /* 語法 */ case LBL_OT3: /* 活用 */ case LBL_OT4: /* 発音 */ case LBL_OT5: /* 地域的異形 */ /* * 類語などのメニューを作る */ if (!strncmp(p, "【類語】", 8)) { if (capital != ot1cap) { if (ot1cap != ' ') fprintf(m3fp, "

\n"); fprintf(m3fp, "

%s

\n

\n", han2zen[capital]); ot1cap = capital; } fprintf(m3fp, "【類語】%s
\n", HTML_FILE, ot1no, title); sprintf(endstr(holdbuf), "\n", ot1no++); } else if (!strncmp(p, "【語法】", 8)) { if (capital != ot2cap) { if (ot2cap != ' ') fprintf(m4fp, "

\n"); fprintf(m4fp, "

%s

\n

\n", han2zen[capital]); ot2cap = capital; } fprintf(m4fp, "【語法】%s
\n", HTML_FILE, ot2no, title); sprintf(endstr(holdbuf), "\n", ot2no++); } else { if (capital != ot3cap) { if (ot3cap != ' ') fprintf(m5fp, "

\n"); fprintf(m5fp, "

%s

\n

\n", han2zen[capital]); ot3cap = capital; } getuptow(p, tmp, "】"); fprintf(m5fp, "%s】%s
\n", HTML_FILE, ot3no, tmp, title); sprintf(endstr(holdbuf), "\n", ot3no++); } if (have_anchor) { hl_generate_anchor(holdbuf, lp->id, cur_ps, cur_tr, cur_trsub, NULL); } goto output; case LBL_TL: /* 文献タイトル */ case LBL_TLSUB: /* 文献タイトルサブ項目 */ /* * "◇"や"[音楽]"を読み飛ばして、 * そこに作品名があれば作品名メニューを作る */ q = p; if (!strncmp(q, "◇", 2)) q += 2; if (*q == '[') { q = getupto(q, tmp, ']') + 1; strcat(tmp, "]"); } if (have_anchor) { hl_generate_anchor(holdbuf, lp->id, cur_ps, cur_tr, cur_trsub, *tmp? tmp: NULL); } if (!*q) goto output; if (capital != tlcap) { if (tlcap != ' ') fprintf(m2fp, "

\n"); fprintf(m2fp, "

%s

\n

\n", han2zen[capital]); tlcap = capital; } conv_html(tmp, q, itemno, "", FALSE); fprintf(m2fp, "%s
\n", HTML_FILE, tlno, tmp); sprintf(endstr(holdbuf), "\n", tlno++); goto output; case LBL_KEYID: /* 成句キー */ if (have_anchor) { strcpy(tmp, p); removetag(tmp); hl_generate_anchor(holdbuf, LBL_KEYID, cur_ps, cur_tr, cur_trsub, tmp); } /* * 複合検索インデックスを作る */ if (!do_complexed_index) break; conv_html(tmp, p, itemno, "", TRUE); q = endstr(holdbuf); if (q - holdbuf > MAX_HOLD - HOLD_MARGIN) write_log("出力保持バッファがもうすぐ一杯です\n"); while ((p = getidxword(p, key)) != NULL) { sprintf(q, "%s\n", tmp, key); q = endstr(q); } *q = '\0'; break; case LBL_PS: /* 品詞 */ strcpy(psbuf, p); cur_ps = removetag(psbuf); cur_tr = cur_trsub = -1; if (have_anchor) { hl_generate_anchor(holdbuf, LBL_PS, cur_ps, cur_tr, cur_trsub, NULL); } goto output; case LBL_TR: /* 語意 */ cur_tr = lp->tr; cur_trsub = -1; if (have_anchor) { hl_generate_anchor(holdbuf, LBL_TR, cur_ps, cur_tr, cur_trsub, NULL); } goto output; case LBL_TRSUB: /* 語意サブ項目 */ cur_tr = lp->tr; cur_trsub = lp->trsub; if (have_anchor) { hl_generate_anchor(holdbuf, LBL_TRSUB, cur_ps, cur_tr, cur_trsub, NULL); } goto output; case LBL_MN: /* 意味 */ cur_tr = 1; cur_trsub = -1; if (have_anchor) { hl_generate_anchor(holdbuf, LBL_TR, cur_ps, cur_tr, cur_trsub, NULL); } goto output; case LBL_KEYEX: /* 用例キー */ if (have_anchor) { hl_generate_anchor(holdbuf, LBL_KEYEX, cur_ps, cur_tr, cur_trsub, NULL); } goto output; case LBL_SRC: /* 語源 */ if (have_anchor) { hl_generate_anchor(holdbuf, LBL_SRC, cur_ps, cur_tr, cur_trsub, NULL); } goto output; case LBL_J2E: /* 日本語から借用 */ if (!strcmp(p, "END")) break; goto output; default: output: if (!lp->disp) break; if (!*p) break; if (have_title) { have_title = FALSE; if (first) first = FALSE; else fprintf(fp, "\n

\n"); if (*holdbuf) { fprintf(fp, "%s", holdbuf); *holdbuf = '\0'; } if (derived) sprintf(drbuf, "DR%02d", derived); else *drbuf = '\0'; fprintf(fp, "
%s
\n", itemno, drbuf, title); while (enp && enp->dpos <= lpos) { tozen(key, enp->fkey); fprintf(fp, "%s\n", title, key); fprintf(fp, "%s\n", title, key); enp = lst_getentry(enfp, &en); } while (trp && trp->dpos <= lpos) { fprintf(fp, "%s\n", title, trp->fkey); fprintf(fp, "%s\n", title, trp->fkey); trp = lst_getentry(trfp, &tr); } fprintf(fp, "

\n"); space = ""; if (have_pron) { have_pron = FALSE; fprintf(fp, "%s%s", space, pron); space = " "; } if (have_variant) { have_variant = FALSE; fprintf(fp, "%s%s", space, variant); space = " "; } if (have_sound) { have_sound = FALSE; fprintf(fp, "%s%s", space, soundref); space = " "; } if (do_quickret && qjp && derived) { fprintf(fp, "%s%s", space, itemno, ret_ref); space = " "; } if (do_quickjump == QJ_INDIRECT && qjp && !derived) { fprintf(fp, "%s%s", space, itemno, jump_ref); space = " "; } else if (do_quickjump && qjp && !derived) { int no = 0; int dr = 1; if (do_quickjump == QJ_NEXTLINE) { fprintf(fp, "
\n%s", indentstr(1)); space = ""; } while (*qjp && *qjp != '\n') { if (do_quickjump == QJ_NEXTNLINE) { fprintf(fp, "
\n%s", indentstr(1)); space = ""; } qjp = getupto(qjp, tmp, '|') + 1; if (strcmp(tmp, "派生形")) { fprintf(fp, "%s%s%s", space, itemno, no++, arrow_ref, tmp); } else if (*qjp && *qjp != '\n') { qjp = getupto(qjp, tmp, '|') + 1; fprintf(fp, "%s%s%s", space, itemno, dr++, arrow_ref, tmp); } space = " "; } } if (!*space) { /* *

title


では * titleのあと改行してくれないので * スペースを1つ入れる */ fprintf(fp, " "); } needbr = TRUE; } if (needbr && lp->id != LBL_ID) { fprintf(fp, "
\n"); needbr = FALSE; } if (*holdbuf && lp->id != LBL_ID && lp->id != LBL_TL) { fprintf(fp, "%s", holdbuf); *holdbuf = '\0'; } if (do_quickjump && qjp && *qjp && (lp->id == LBL_PS || lp->id == LBL_OT1 || lp->id == LBL_OT2 || lp->id == LBL_OT3 || lp->id == LBL_OT4 || lp->id == LBL_OT5 || lp->id == LBL_ID && newidiom)) { fprintf(fp, "\n", itemno, qjno++); } switch (lp->id) { case LBL_EX: /* 用例 */ case LBL_NB: /* 註 */ case LBL_NBP: /* 表現註 */ case LBL_NBSUB: /* 註サブ項目 */ case LBL_NBPSUB: /* 表現註サブ項目 */ case LBL_NSBUS: /* NBSUBの誤記???(and) */ indent = indentstr(2); break; default: indent = indentstr(1); break; } switch (lp->id) { case LBL_PS: /* 品詞 */ conv_html(htmlbuf, p, itemno, srchkey, TRUE); fprintf(fp, "%s━%s", indent, htmlbuf); if (do_quickret && qjp && !derived) fprintf(fp, "%s", itemno, ret_ref); newidiom = TRUE; break; case LBL_TRSUB: /* 語意サブ項目 */ if (!strncmp(p, "【", 2)) p = skipwch(p, "】"); conv_html(htmlbuf, p, itemno, srchkey, TRUE); fprintf(fp, "%s%s", indent, htmlbuf); break; case LBL_ID: /* 成句 */ if (newidiom) { if (needbr) { fprintf(fp, "
\n"); needbr = FALSE; } fprintf(fp, "%s<成句>", indent); if (do_quickret && qjp) fprintf(fp, "%s", itemno, ret_ref); newidiom = FALSE; } conv_html(htmlbuf, p, itemno, srchkey, TRUE); fprintf(fp, "\n

\n

\n"); if (*holdbuf) { fprintf(fp, "%s", holdbuf); *holdbuf = '\0'; } fprintf(fp, "%s%s", indent, htmlbuf); break; case LBL_EX : /* 用例 */ if (!do_complexed_index) { conv_html(htmlbuf, p, itemno, srchkey, TRUE); fprintf(fp, "%s%s", indent, htmlbuf); break; } /* * " "があればその直前まで、 * なければ全体をクロス条件検索に登録 * 同時に複合検索にも登録される */ if ((q = strstr(p, " ")) != NULL) { *q = '\0'; /* * 用例本体にあるタグはすべて捨てる * そうしないとEBStudioが検索用の単語を * クロス条件検索ではなく前方一致検索 * インデックスのほうに登録してしまうため * (2004/12/11現在のEBStudioの制約) */ conv_example(htmlbuf, p); conv_html(tmp, q+6, itemno, srchkey, TRUE); *q = ' '; fprintf(fp, "%s%s %s", indent, htmlbuf, tmp); } else { conv_html(htmlbuf, p, itemno, srchkey, TRUE); fprintf(fp, "%s%s", indent, htmlbuf); } break; case LBL_OT1: /* 類語 */ case LBL_OT2: /* 語法 */ case LBL_OT3: /* 活用 */ case LBL_OT4: /* 発音 */ case LBL_OT5: /* 地域的異形 */ fprintf(fp, "%s", indent); if (!strncmp(p, "【", 2)) { p = getuptow(p+2, tmp, "】") + 2; fprintf(fp, "<%s>", tmp); if (do_quickret && qjp) fprintf(fp, "%s", itemno, ret_ref); } if (*p) { conv_html(htmlbuf, p, itemno, srchkey, TRUE); fprintf(fp, "
\n%s%s", indent, htmlbuf); } break; case LBL_TL: /* 文献タイトル */ if (!strncmp(p, "◇", 2)) { fprintf(fp, "%s◆作品名", indent); p += 2; if (!*p) break; fprintf(fp, "
\n"); } if (*holdbuf) { fprintf(fp, "%s", holdbuf); *holdbuf = '\0'; } conv_html(htmlbuf, p, itemno, srchkey, TRUE); fprintf(fp, "%s%s", indent, htmlbuf); break; case LBL_IMG: break; default: conv_html(htmlbuf, p, itemno, srchkey, TRUE); fprintf(fp, "%s%s", indent, htmlbuf); break; } needbr = TRUE; break; } } do { hl_warn_undone(); cnt += hl_flush_anchor(fp, &needbr); } while (hl_getentry(hlfp) != NULL); if (cnt > 0) { fprintf(fp, "%s%s", indentstr(1), itemno, ret_ref); needbr = TRUE; } fprintf(fp, "\n

\n"); if (do_quickjump == QJ_INDIRECT) { rewind(qjfp); indent = indentstr(1); while (qj_getline(qjfp, qjbuf) != -1L) { int no = 0; int dr = 1; fprintf(fp, "ἃ\nἂ\n"); qjp = skipch(qjbuf, '|'); qjp = getupto(qjp, itemno, '|') + 1; qjp = getupto(qjp, key, '|') + 1; fprintf(fp, "
%s
\n


\n", itemno, key); needbr = FALSE; while (*qjp && *qjp != '\n') { if (needbr) { fprintf(fp, "
\n"); needbr = FALSE; } qjp = getupto(qjp, tmp, '|') + 1; if (strcmp(tmp, "派生形")) { fprintf(fp, "%s%s%s", indent, itemno, no++, arrow_ref, tmp); } else if (*qjp && *qjp != '\n') { qjp = getupto(qjp, tmp, '|') + 1; fprintf(fp, "%s%s%s", indent, itemno, dr++, arrow_ref, tmp); } needbr = TRUE; } fprintf(fp, "\n

\n"); } } dic_close(mainfp); lst_close(enfp); lst_close(trfp); if (do_quickjump) qj_close(qjfp); hl_close(hlfp); if (do_figure) dat_close(imgfd); if (do_sound) dat_close(sndfd); html_close(fp); if (do_figure) menu_close(m1fp); menu_close(m2fp); menu_close(m3fp); menu_close(m4fp); menu_close(m5fp); if (do_sound && generate_sound && macintosh) { pl_close(plfp, sndfiles - (sndfiles % 10000L) + 1L, sndfiles); pl_close(plafp, 1L, sndfiles); } printf("\r本文データをHTMLに変換しています... "); message("終了しました\n"); hlno_pass2 = next_hlno() - 1; if (hlno_pass2 != hlno_pass1) { message("ハイパーリンクタグの個数が生成時(%d)と参照時(%d)で異なっています\n", hlno_pass1, hlno_pass2); return ERR; } return OK; } /* * 著作権表示ファイルを生成する */ int generate_copyright_file(void) { int c, lastc, holdsp; byte *p, buf[MAX_PATH]; FILE *ifp, *ofp; sprintf(buf, "%s%s", dic_path, README_FILE); if ((ifp = fopen(buf, "rb")) == NULL) { message("ファイル %s がオープンできません\n", buf); return ERR; } sprintf(buf, "%s%s", base_path, COPR_FILE); if ((ofp = fopen(buf, "w")) == NULL) { message("著作権表示ファイル %s が新規作成できません\n", buf); return ERR; } message("著作権表示ファイルを生成しています... "); fprintf(ofp, "\n"); fprintf(ofp, "\n"); fprintf(ofp, "著作権表示\n"); fprintf(ofp, "\n"); fprintf(ofp, "\n"); fprintf(ofp, "

\n"); lastc = '\0'; holdsp = FALSE; while ((c = getc(ifp)) != EOF && c != 0x1a) { if (c == '\r') { fprintf(ofp, "

\n

"); } else if (c == '\n') { if (lastc != '\r') fprintf(ofp, "

\n

"); } else if (c == ' ') { if (holdsp) { fprintf(ofp, " "); holdsp = FALSE; } else { holdsp = TRUE; } } else { if (holdsp) { putc(' ', ofp); holdsp = FALSE; } putc(c, ofp); } lastc = c; } fprintf(ofp, "

\n"); fprintf(ofp, "\n"); fprintf(ofp, "\n"); fclose(ifp); fclose(ofp); message("終了しました\n"); return OK; } /* * 複合検索定義ファイルを生成する */ int generate_complex_file(void) { byte buf[MAX_PATH]; FILE *fp; sprintf(buf, "%s%s", base_path, CMPL_FILE); if ((fp = fopen(buf, "w")) == NULL) { message("複合検索定義ファイル %s が新規作成できません\n", buf); return ERR; } message("複合検索定義ファイルを生成しています... "); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, " \n"); fprintf(fp, " \n"); fprintf(fp, " \n"); fprintf(fp, " \n"); fprintf(fp, " \n"); fprintf(fp, " \n"); fprintf(fp, " \n"); fprintf(fp, "\n"); fclose(fp); message("終了しました\n"); return OK; } /* * EBStudio定義ファイルsrd.ebsを生成する */ 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=0\n"); fprintf(fp, "WordSearchHyoki=1\n"); fprintf(fp, "WordSearchKana=0\n"); fprintf(fp, "EndWordSearchHyoki=1\n"); fprintf(fp, "EndWordSearchKana=0\n"); fprintf(fp, "KeywordSearch=%d\n", do_complexed_index); fprintf(fp, "ComplexSearch=%d\n", do_complexed_index); 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=%d\n", (do_figure || do_sound)? 1: 0); fprintf(fp, "inlineImg=0\n"); fprintf(fp, "paraHdr=0\n"); fprintf(fp, "ruby=1\n"); fprintf(fp, "paraBr=0\n"); fprintf(fp, "subTitle=1\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=1\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=220000;390000;100;229000000;82000;3300000;100;2600;106500;10100;3100\n"); fprintf(fp, "Book=ランダムハウス英語辞典;SRD;英和辞典;$(BASE)\\%s;", COPR_FILE); if (do_complexed_index) { fprintf(fp, "$(BASE)\\%s;", CMPL_FILE); } else { fprintf(fp, "_;"); } fprintf(fp, "GAI16H00;GAI16F00;_;_;_;_;_;_;\n"); fprintf(fp, "Source=$(BASE)\\%s;本文;_;HTML;\n", HTML_FILE); if (do_figure) fprintf(fp, "Source=$(BASE)\\%s;図版;_;HTML;\n", MENU1_FILE); fprintf(fp, "Source=$(BASE)\\%s;作品名;_;HTML;\n", MENU2_FILE); fprintf(fp, "Source=$(BASE)\\%s;類語;_;HTML;\n", MENU3_FILE); fprintf(fp, "Source=$(BASE)\\%s;語法;_;HTML;\n", MENU4_FILE); fprintf(fp, "Source=$(BASE)\\%s;活用他;_;HTML;\n", MENU5_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, "DICPATH")) { if (p[-1] != '/' && p[-1] != '\\') strcat(val, "\\"); dic_path = strdup(val); } else if (!strcmp(key, "DATAPATH")) { if (p[-1] != '/' && p[-1] != '\\') strcat(val, "\\"); data_path = strdup(val); } else if (!strcmp(key, "SORTCMD")) sort_cmd = strdup(val); else if (!strcmp(key, "MACINTOSH")) macintosh = n; else if (!strcmp(key, "FIGURE")) do_figure = n; else if (!strcmp(key, "JPEG")) use_jpeg = n; else if (!strcmp(key, "SOUND")) do_sound = n; else if (!strcmp(key, "GENSOUND")) generate_sound = n; else if (!strcmp(key, "COMPLEX")) do_complexed_index = n; else if (!strcmp(key, "QUICKJUMP")) do_quickjump = n; else if (!strcmp(key, "QJITEMS")) qj_items = n; else if (!strcmp(key, "QJLINES")) qj_lines = n; else if (!strcmp(key, "QUICKRET")) do_quickret = n; else if (!strcmp(key, "ITALIC")) use_italic = n; else if (!strcmp(key, "PRONSYM")) pron_sym = strdup(val); else if (!strcmp(key, "JUMPSYM")) jump_sym = strdup(val); else if (!strcmp(key, "ARROWSYM")) arrow_sym = strdup(val); else if (!strcmp(key, "RETSYM")) ret_sym = strdup(val); else { message("設定ファイルに不正な行があります(%d行め)\n", lineno); ret = ERR; } } fclose(fp); message("変換設定は以下のとおりです\n"); message(" BASEPATH = %s\n", base_path); message(" OUTPATH = %s\n", out_path); message(" DICPATH = %s\n", dic_path); message(" DATAPATH = %s\n", data_path); message(" SORTCMD = %s\n", sort_cmd); message(" MACINTOSH = %d\n", macintosh); message(" FIGURE = %d\n", do_figure); message(" JPEG = %d\n", use_jpeg); message(" SOUND = %d\n", do_sound); message(" GENSOUND = %d\n", generate_sound); message(" COMPLEX = %d\n", do_complexed_index); message(" QUICKJUMP = %d\n", do_quickjump); message(" QJITEMS = %d\n", qj_items); message(" QJLINES = %d\n", qj_lines); message(" QUICKRET = %d\n", do_quickret); message(" ITALIC = %d\n", use_italic); message(" PRONSYM = %s\n", pron_sym); message(" JUMPSYM = %s\n", jump_sym); message(" ARROWSYM = %s\n", arrow_sym); message(" RETSYM = %s\n", ret_sym); 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 (do_figure) { sprintf(path, "%s%s", base_path, FIG_DIR); 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; } strcat(path, "\\"); figure_path = strdup(path); } if (do_sound && generate_sound) { sprintf(path, "%s%s", base_path, SND_DIR); 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; } strcat(path, "\\"); sound_path = strdup(path); sound_path_slash = strdup(sound_path); for (p = sound_path_slash; *p; p++) { if (*p == '\\') *p = '/'; } } 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) { if (do_figure) { if (use_jpeg) message("※ %s にある図版データをJPEG形式に変換してください\n", figure_path); else if (macintosh) message("※ %s にある図版データをBMP形式に変換してください\n", figure_path); } if (do_sound && generate_sound) message("※ %s にある音声データを無圧縮WAV形式に変換してください\n", sound_path); message("※ "); if (do_figure && use_jpeg || do_sound && generate_sound) message("その後 "); 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 (init_gaiji() == ERR) term(ERR); if (do_quickjump) { if (generate_quickjump_file() == ERR) term(ERR); } if (generate_hyperlink_file() == ERR) term(ERR); if (do_convert() == ERR) term(ERR); if (generate_copyright_file() == ERR) term(ERR); if (do_complexed_index) { if (generate_complex_file() == ERR) term(ERR); } if (generate_ebs_file() == ERR) term(ERR); term(OK); }