sj3/makelist.c

537 lines
10 KiB
C

/*
* Copyright (c) 1991-1994 Sony Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Sony Corporation
* shall not be used in advertising or otherwise to promote the sale, use
* or other dealings in this Software without prior written authorization
* from Sony Corporation.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "sj_struct.h"
#include "dicttool.h"
#ifndef SS2
#define SS2 0x8e
#endif
extern DouonRec* douon_ptr;
extern int douon_num;
extern int yomi_len;
extern int hinshi_num;
extern int kanji_len;
extern HindoRec* hindo[];
extern int hindo_num;
extern HindoRec* askknj[];
extern int askknj_num;
extern HindoRec* asshuku;
static DouonRec* drectmp = NULL;
static void
clearklist(KanjiRec* krec) {
KanjiRec* p;
while(krec) {
Free(krec->kptr);
Free(krec->aptr);
p = krec;
krec = krec->knext;
Free(p);
}
}
static void
clearhlist(HinshiRec* hrec) {
HinshiRec* p;
while(hrec) {
clearklist(hrec->krec);
p = hrec;
hrec = hrec->hnext;
Free(p);
}
}
void clear_list(void) {
DouonRec* p;
DouonRec* drec = douon_ptr;
while(drec) {
Free(drec->yptr);
clearhlist(drec->hrec);
p = drec;
drec = drec->dnext;
Free(p);
}
douon_ptr = NULL;
}
static unsigned char*
makekanji(int* yomi, int* kanji, int* atr, int* len) {
int kana[MaxYomiLength + 1];
unsigned char ktmp[MaxKanjiLength * 3 + MaxAtrNumber * 2 + 1];
int i;
int pos = 0;
int* p;
unsigned char* q;
for(p = yomi, i = 0; *p;)
kana[i++] = h2kcode(*p++);
kana[i] = 0;
while(*atr) {
i = *atr;
atr++;
#ifndef NO_ATR
ktmp[pos++] = (AiAttribute | ((i >> 8) & 0xff));
ktmp[pos++] = (i & 0xff);
#endif
}
if((i = top_strcmp(yomi, kanji)) != 0) {
kanji += i;
ktmp[pos++] = (ZenHiraAsshuku | (i - 1));
}
else if((i = top_strcmp(kana, kanji)) != 0) {
kanji += i;
ktmp[pos++] = (ZenKataAsshuku | (i - 1));
}
while(*kanji) {
if((i = last_strcmp(yomi, kanji)) != 0) {
kanji += i;
ktmp[pos++] = (ZenHiraAsshuku | (i - 1));
}
else if((i = last_strcmp(kana, kanji)) != 0) {
kanji += i;
ktmp[pos++] = (ZenKataAsshuku | (i - 1));
}
else if(((*kanji >> 8) & 0xff) == SS2 || *kanji < 0x100) {
ktmp[pos] = LeadingHankaku;
ktmp[pos + 1] = (*kanji & 0xff);
kanji++;
pos += 2;
}
else {
if(*kanji < 0x10000) {
ktmp[pos] = ((*kanji >> 8) & NormalKanjiMask);
ktmp[pos + 1] = (*kanji & NormalKanjiMask);
kanji++;
pos += 2;
} else if(*kanji < 0x1000000) {
ktmp[pos] = ((*kanji >> 8) & NormalKanjiMask);
ktmp[pos + 1] = (*kanji & 0xff);
kanji++;
pos += 2;
} else {
fprintf(stderr, "Error: 4 byte code is found\n");
exit(0);
}
}
}
*len = pos;
q = (unsigned char*)Malloc(pos);
if(!q) {
fprintf(stderr, "\245\341\245\342\245\352\244\254\311\324\302\255\244\267\244\336\244\267\244\277");
exit(1);
}
memcpy(q, ktmp, pos);
return q;
}
static unsigned char*
makeyomi(int* yomi) {
unsigned char tmp[MaxYomiLength + 1];
int i;
int j;
int* y = yomi;
unsigned char* p;
for(i = 0; *y;) {
j = cnvyomi(*y++);
if(j == 0) {
fprintf(stderr, "\311\324\300\265\244\312\312\270\273\372\244\254\306\311\244\337\244\313\273\310\244\357\244\354\244\306\244\244\244\336\244\271\n");
output_int(stderr, yomi);
fputc('\n', stderr);
exit(1);
}
tmp[i++] = j;
}
tmp[i++] = 0;
p = (unsigned char*)Malloc(i);
if(!p) {
fprintf(stderr, "\245\341\245\342\245\352\244\254\311\324\302\255\244\267\244\336\244\267\244\277");
exit(1);
}
memcpy(p, tmp, i);
return p;
}
static KanjiRec*
make_krec(unsigned char* kcode, int klen) {
KanjiRec* krec;
krec = (KanjiRec*)Malloc(sizeof(KanjiRec));
if(!krec) {
fprintf(stderr, "\245\341\245\342\245\352\244\254\311\324\302\255\244\267\244\336\244\267\244\277");
exit(1);
}
krec->klen = klen;
krec->kptr = kcode;
krec->alen = 0;
krec->aptr = NULL;
krec->knext = NULL;
return krec;
}
static HinshiRec*
make_hrec(int hinshi) {
HinshiRec* hrec;
hrec = (HinshiRec*)Malloc(sizeof(HinshiRec));
if(!hrec) {
fprintf(stderr, "\245\341\245\342\245\352\244\254\311\324\302\255\244\267\244\336\244\267\244\277");
exit(1);
}
hrec->hinshi = hinshi;
hrec->krec = NULL;
hrec->hnext = NULL;
return hrec;
}
static DouonRec*
make_drec(unsigned char* ycode) {
DouonRec* drec;
drec = (DouonRec*)Malloc(sizeof(DouonRec));
if(!drec) {
fprintf(stderr, "\245\341\245\342\245\352\244\254\311\324\302\255\244\267\244\336\244\267\244\277");
exit(1);
}
drec->yptr = ycode;
drec->hrec_num = 0;
drec->hrec = NULL;
drec->dnext = NULL;
return drec;
}
static int
diff_ylen(DouonRec* drec) {
DouonRec* dptr;
DouonRec* dprev;
unsigned char* p1;
unsigned char* p2;
int ylen = 0;
dptr = douon_ptr;
dprev = NULL;
while(dptr) {
dprev = dptr;
dptr = dptr->dnext;
}
if(dprev) {
p1 = dprev->yptr;
p2 = drec->yptr;
while(*p1 && (*p1 == *p2)) {
p1++;
p2++;
}
if(*p1 == *p2) {
fprintf(stderr, "\305\371\244\267\244\244\306\311\244\337\244\316\306\261\262\273\270\354\245\326\245\355\245\303\245\257\244\254\244\242\244\353\n");
output_yomi(stderr, dprev->yptr);
fputc('\n', stderr);
exit(1);
}
else if(*p1 > *p2) {
fprintf(stderr, "\306\311\244\337\244\316\275\347\275\370\244\254\244\252\244\253\244\267\244\244\n");
output_yomi(stderr, dprev->yptr);
fputc('\n', stderr);
output_yomi(stderr, drec->yptr);
fputc('\n', stderr);
exit(1);
}
while(*p2++) ylen++;
}
return ylen;
}
static int
douon_knj(DouonRec* drec) {
int i;
int len = 0;
unsigned char* p;
unsigned char* knjofscvt();
HinshiRec* hrec;
KanjiRec* krec;
for(hrec = drec->hrec; hrec; hrec = hrec->hnext) {
for(krec = hrec->krec; krec; krec = krec->knext) {
p = knjofscvt(krec->kptr, krec->klen, &i);
len += i + 1;
knjhnd_set(p, i);
krec->alen = i;
krec->aptr = p;
set_ofsrec(krec->kptr, krec->klen, 0);
}
}
return len;
}
static void
make_d_list(DouonRec* drec) {
DouonRec *dptr, *dprev;
HinshiRec* hptr;
KanjiRec* kptr;
int ylen;
int klen;
int hnum;
int len;
int i;
start:
if(douon_ptr == NULL) {
douon_num = 0;
yomi_len = 0;
hinshi_num = 0;
kanji_len = 0;
asshuku = NULL;
}
klen = douon_knj(drec);
ylen = diff_ylen(drec);
hnum = drec->hrec_num;
i = 1 +
MaxKnjAskNumber +
douon_num * DouonBlkSizeNumber + DouonBlkSizeNumber +
yomi_len + ylen +
hinshi_num + hnum +
hinshi_num + hnum +
kanji_len + klen;
len = (i <= MainSegmentLength) ? 0 : decide_knjask();
if((i - len) <= MainSegmentLength) {
if(douon_ptr) {
dptr = douon_ptr;
dprev = NULL;
while(dptr) {
dprev = dptr;
dptr = dptr->dnext;
}
dprev->dnext = drec;
}
else {
douon_ptr = drec;
}
drec->dnext = NULL;
drec->dlen = ylen;
douon_num += 1;
yomi_len += ylen;
hinshi_num += hnum;
kanji_len += klen;
return;
}
else if(douon_ptr == NULL) {
fprintf(stderr, "\243\261\306\261\262\273\270\354\245\326\245\355\245\303\245\257\244\254\302\347\244\255\244\271\244\256\244\336\244\271\n");
exit(1);
}
for(hptr = drec->hrec; hptr; hptr = hptr->hnext) {
for(kptr = hptr->krec; kptr; kptr = kptr->knext) {
knjhnd_reset(kptr->aptr, kptr->alen);
Free(kptr->aptr);
kptr->aptr = NULL;
}
}
len = decide_knjask();
makeseg();
clear_list();
clear_hindo();
clear_ofsrec();
askknj_num = 0;
clear_asshuku();
goto start;
}
void flush_douon(void) {
if(drectmp) {
make_d_list(drectmp);
drectmp = NULL;
}
if(douon_ptr) {
decide_knjask();
makeseg();
clear_list();
clear_hindo();
clear_ofsrec();
askknj_num = 0;
}
}
void makelist(int* yomi, int* kanji, int hinshi, int* atr) {
unsigned char* ycode;
unsigned char* kcode;
int klen;
HinshiRec* hrec;
KanjiRec * krec, *kprev;
ycode = makeyomi(yomi);
kcode = makekanji(yomi, kanji, atr, &klen);
if(drectmp && strcmp(ycode, drectmp->yptr)) {
make_d_list(drectmp);
drectmp = NULL;
}
if(!drectmp) {
drectmp = make_drec(ycode);
hrec = make_hrec(hinshi);
drectmp->hrec = hrec;
drectmp->hrec_num = 1;
krec = make_krec(kcode, klen);
hrec->krec = krec;
return;
}
for(hrec = drectmp->hrec; hrec->hnext; hrec = hrec->hnext)
if(hrec->hinshi == hinshi) break;
if(hrec->hinshi == hinshi) {
for(krec = hrec->krec; krec; krec = krec->knext) {
if((krec->klen == klen) &&
!memcmp(krec->kptr, kcode, klen)) {
fprintf(stderr, "\306\261\260\354\244\316\275\317\270\354\244\254\302\270\272\337\244\267\244\277\n");
fprintf(stderr, "\t\306\311\244\337:");
output_int(stderr, yomi);
fprintf(stderr, "\n");
fprintf(stderr, "\t\264\301\273\372:");
output_int(stderr, kanji);
fprintf(stderr, "\n");
Free(kcode);
return;
}
kprev = krec;
}
kprev->knext = make_krec(kcode, klen);
return;
}
hrec->hnext = make_hrec(hinshi);
hrec = hrec->hnext;
drectmp->hrec_num += 1;
krec = make_krec(kcode, klen);
hrec->krec = krec;
}