/* vi: set sw=4 ts=4: */ #include #include #include #include #include #include "defs.h" #include "convert.h" #include "hzinput.h" #include "pinyin.h" #include "zhuyin.h" #include "cin2tab.h" static char *phrase_fname; typedef struct _HzPhrase { u_char hz[MAX_PYPHRASE_LEN*2+1]; PYFREQTYPE freq; struct _HzPhrase *next; }HzPhrase; typedef struct _KeyPhrase { u_short len; u_char key[2*MAX_PYPHRASE_LEN+1]; u_short count; /* number of Phrase items, in file it should be u_char */ HzPhrase *hzph; struct _KeyPhrase *next; }KeyPhrase, *PKeyPhrase; static PKeyPhrase phtab[MAX_PY_NUM]; static u_short phcount[MAX_PY_NUM]; static char strarr[4*MAX_PYPHRASE_LEN][2*MAX_PYPHRASE_LEN+1]; static u_short KeyAhead(u_char *key) { #if 1 /* 9 bit */ u_short py; py = (short)key[1]; py |= (key[0] & 0x01) << 8; return py; #else u_short py; py = '\0'; py |= key[0] << 2 & 0x3ff; py |= key[1] >> 6; return py; #endif } static void PYKey2Key(u_char *key, u_short *pykey, u_char len) { #if 1 int i; for(i=0; i> (8-i); #else int i,j,p; int klen=(len*10)/8 +1; for (j=0; j> (2 + p); key[j] |= pykey[i] << (6 - p) ; p += 2; if ( (p %= 8) == 0 ) j++; } #endif } static int String2Array(char *strbuf,int len, int maxcount, char strarr[][2*MAX_PYPHRASE_LEN+1]) { int i=0, cursor=0, count=0, buflen = strlen(strbuf); strarr[0][0] = '\0'; while(i < buflen) { while(strbuf[i] == ' ' || strbuf[i] == '\t' || strbuf[i] == '\'') i++; /* skip space and ' */ cursor = i; if (strbuf[i] == '\0' || strbuf[i] == '#' || strbuf[i] == '\r' || strbuf[i] == '\n') break; while(i < buflen && strbuf[i] != ' ' && strbuf[i] != '\t' && strbuf[i] != '\'' && strbuf[i] != '#' && strbuf[i] != '\r' && strbuf[i] != '\n') i++; /* skip non-space pinyins */ if (i > cursor) { if (i - cursor >= len) cursor = i - len + 1; /* for safety, take the last len bytes, add one 0 */ strncpy(strarr[count],strbuf+cursor,i-cursor); strarr[count++][i-cursor] = '\0'; if (count >= maxcount) return count; } } return count; } static int total_phrase = 0; static int SavePhraseToMem(u_char *str,u_char *key, u_short len, PYFREQTYPE freq) { PKeyPhrase kph,tmpkph; HzPhrase *hzph; int first; short ahead; static int hzlen[10]; if (len<1) return 0; if (len > MAX_PYPHRASE_LEN) { fprintf(stderr, "Phrase %s(len %d) exceeded max phrase len(%d)\n", str, len, MAX_PYPHRASE_LEN); return 0; } ahead = (short)KeyAhead(key); kph = phtab[ahead]; if (kph != NULL) /* first phrase of this pinyin */ { first=1; do { if (first) first = 0; else kph = kph->next; if (kph->len == len && !memcmp(kph->key,key, PYKEYLEN(len) )) { for(hzph = kph->hzph; hzph != NULL; hzph = hzph->next) if ( len != 1 && !memcmp(hzph->hz,str,2*len)) /* same phrase */ { #ifdef DEBUG fprintf(stderr,"Duplicate phrase %s detected, ignored!\n", hzph->hz); #endif return 0; } hzph = kph->hzph; while(hzph->next != NULL) hzph = hzph->next; /* reach the end of the link list */ if ((hzph->next = (HzPhrase *)malloc(sizeof(HzPhrase)))==NULL) { fprintf(stderr,"SavePhraseToMem: no enough memory\n"); exit(1); } kph->count++; hzph = hzph->next; hzph->freq = freq; hzph->next = NULL; memcpy(hzph->hz,str,len*2); /* len < MAX_PYPHRASE_LEN */ hzph->hz[len*2] = '\0'; total_phrase++; return 1; /* insert a new Hanzi Phrase at the end of the link list */ } }while(kph->next != NULL); } if ((tmpkph = (KeyPhrase *)malloc(sizeof(KeyPhrase))) == NULL) { fprintf(stderr,"SavePhraseToMem: not enough memory\n"); exit(1); } if (phtab[ahead] == NULL) phtab[ahead] = tmpkph; else kph->next = tmpkph; tmpkph->len = len; tmpkph->count = 1; memcpy(tmpkph->key,key, PYKEYLEN(len) ); /* len < MAX_PYPHRASE_LEN */ tmpkph->next = NULL; if ((tmpkph->hzph = (HzPhrase *)malloc(sizeof(HzPhrase))) == NULL) { fprintf(stderr,"no enough memory\n"); exit(1); } tmpkph->hzph->freq = freq; tmpkph->hzph->next = NULL; memcpy(tmpkph->hzph->hz,str,len*2); /* len < MAX_PYPHRASE_LEN */ tmpkph->hzph->hz[len*2] = '\0'; phcount[ahead]++; hzlen[len]++; total_phrase++; return 1; } static int SavePhraseToFile(FILE *out, int type) { KeyPhrase *kph,*kphtmp; HzPhrase *hzph,*hzphtmp; u_short j; u_char key[MAX_PYKEY_LEN]; u_short len,/* count,*/ size; int max_count = 0; int file_size = 0; for (j=1; jhzph; kphtmp = kph; kph = kph->next; len = kphtmp->len; if (len > MAX_PYPHRASE_LEN) { fprintf(stderr, "buffer overrun\n"); abort(); } memcpy(key,kphtmp->key, PYKEYLEN(len) ); fwrite(&len,sizeof(len),1, out); /* + 2 */ size = kphtmp->count; if (kphtmp->count > 65530 ) /* 2 bytes? */ { fprintf(stdout,"Phrase Count = %d > 65535, error!!!\n",kphtmp->count); exit(1); } fwrite(&size,sizeof(size),1,out); /* +2 */ fwrite(key,sizeof(u_char),PYKEYLEN(len),out); if (kphtmp->count > max_count) max_count = kphtmp->count; file_size += SizeOfPhrase(len,kphtmp->count); while (hzph != NULL) { hzphtmp = hzph; hzph = hzph->next; fwrite(hzphtmp->hz,sizeof(char),len*2,out); fwrite(&(hzphtmp->freq),sizeof(PYFREQTYPE),1,out); free(hzphtmp); } free(kphtmp); } } if (type == 1) file_size += sizeof(hz_input_table); fwrite(&file_size,sizeof(file_size),1,out); fprintf(stderr, "%s:\tFileSize=%d\tTotalPhraseNum=%d\n", phrase_fname, file_size+4, total_phrase); /* last integer */ total_phrase = 0; /* clear it up after saving */ return 1; } #if 0 static void PrintPYMap(FILE *fp) { int i, j, count; count = 0; for(i = 0; i < 26; i++) { for(j = 0; PYMap[i][j].key; j++) fprintf(fp, "%6d ahead=0x%04X %s\n", ++count, ((i+1) << 8) | (j+1), PYMap[i][j].py); } } #endif int ConvertGBPhraseFormat(int mode, char *filename) { FILE *stream; FILE *fout = stdout; int i; char str[512]; u_short len; int count,freq; u_char *p; YinFormat = PINYIN_FORMAT; /* default is pinyin */ stream = fopen(filename, "r"); if (!stream || !fout) return -1; fprintf(stderr, "Now converting GBPhrase file %s mode %d...\n", filename, mode); while ( !feof( stream )) { if ( fgets(str,sizeof(str),stream) != NULL) { p = FilterFormatOptions(str, SYSPH_MAP_STR); if (p == PTR_CONTINUE) { fprintf(fout, "%s", str); continue; } else if (p == PTR_BREAK) { fprintf(fout, "%s", str); break; /* end */ } count = String2Array(p, sizeof(strarr[0]), sizeof(strarr)/sizeof(strarr[0]), strarr); len = strlen(strarr[0])/2; if ((len != count-1 && len != count-2) || len > MAX_PYPHRASE_LEN || count == 0 || len < 1) { fprintf(stderr,"Phrase error len=%d maxlen=%d yin=%d: %s", len, MAX_PYPHRASE_LEN, count-1, p); continue; } if (len == count-2) { freq = atoi(mode == 1 ? strarr[1] : strarr[count-1]); if (freq > 250) freq = 250; count--; } else freq = 0; if (mode == 0) { fprintf(fout, "%s\t%d", strarr[0], freq); for (i=1; i 0; i--) fprintf(fout, "%c", ' '); } for(i = 0; i < len; i++) { u_short index = ZYToPYMap[yin[i][0] & 0x07FF]; if (index == 0) { fprintf(stderr, "Unknow yin 0x%04X Phrase %s(len=%d)\n", index, c,len); fprintf(fout, " ????? %d\n", freq); return -1; } pykey[i] = INDEX_TO_PYMAP(index).key; if (fout) fprintf(fout, "%s ", GET_PYMAP_PY(index)); } if (fout) fprintf(fout, " %d\n", freq); PYKey2Key(key, pykey, len); SavePhraseToMem(c,key,len,freq); } return 0; } static int LoadOnePinyinAndConvert(char *py, char *str) { int j, ahead, flag = 0, len; ahead = (int)py[0]-'a'; flag = 0; if (ahead<0 || ahead>25) { fprintf(stderr,"Phrase error invalid pinyin: %s, py %s", str, py); return -1; } len = strlen(py); if (strchr("012345", py[len-1])) py[len-1] = '\0'; /* override the tone 0~5 */ for(j=0; PYMap[ahead][j].key; j++) { if (!strcmp(PYMap[ahead][j].py,py)) { return PYMap[ahead][j].key; } } if (!flag) { #ifdef DEBUG fprintf(stderr,"Phrase error no pinyin mapping found: %s", str); #endif } return -1; } static int LoadPhraseFromFile(FILE *stream) { int i, ret; int len, count, freq; u_char key[MAX_PYPHRASE_LEN+1]; u_short pykey[MAX_PYPHRASE_LEN]; u_char *p, *c; YinFormat = PINYIN_FORMAT; /* default is pinyin */ while ( !feof( stream )) { if ( fgets(LineBuf,LINE_BUFFER_LEN,stream) != NULL) { p = FilterFormatCharFreq(LineBuf, SYSPH_MAP_STR, &c, &len, &freq, YinFormat == ZHUYIN_FORMAT ? 1: 0 ); if (p == PTR_CONTINUE) continue; else if (p == PTR_BREAK) break; /* end */ if (YinFormat == ZHUYIN_FORMAT) { HandleZhuyinFormat(p, c, len, freq, NULL); /* stdout); */ continue; } count = String2Array(p, sizeof(strarr[0]), sizeof(strarr)/sizeof(strarr[0]), strarr); if ( len > MAX_PYPHRASE_LEN || len < 1 || count < len || count % len != 0) { fprintf(stderr,"Phrase error len=%d maxlen=%d yin=%d: %s", len, MAX_PYPHRASE_LEN, count, p); continue; } count -= count % len; for (i=0; i < count; i++) { ret = LoadOnePinyinAndConvert(strarr[i], p); if (ret < 0) /* fail! */ { #ifdef DEBUG #endif break; } pykey[i % len] = (u_short)ret; if (((i+1) % len) == 0) /* a complete yin */ { PYKey2Key(key, pykey, len); SavePhraseToMem(c,key,len,freq); } } } } return (0); } int ConvertPinyinCIN(FILE *fr, hz_input_table *table, char *filename ) { int i=0; FILE *fw; OldCoding = NewCoding = table->encoding; if ((fw=fopen(filename,"w"))==NULL) print_error("Failed to create output file!"); phrase_fname = filename; fwrite(table,sizeof(*table),1, fw); #if 0 cmd_arg(fr,LineBuf, &cmd, &arg); if (LoadFileSection( cmd, arg, PINYIN_MAP_STR, fr, LoadPinyinTable)) print_error("%" PINYIN_MAP_STR " [ | begin ] expected!"); fwrite(&PYMap, sizeof(PYMap),1, fw); /* write the pinyin tab */ cmd_arg(fr,LineBuf, &cmd, &arg); if (LoadFileSection( cmd, arg, PYZY_MAP_STR, fr, LoadZhuyinToPinyinMap)) print_error("%" PYZY_MAP_STR " [ | begin ] expected!"); fwrite(&ZYToPYMap, sizeof(ZYToPYMap), 1, fw); #endif if (LoadFileSection( cmd, arg, SYSPH_MAP_STR, fr, LoadPhraseFromFile)) print_error("%" SYSPH_MAP_STR " [ | begin ] expected!"); do { cmd_arg(fr,LineBuf, &cmd, &arg); } while (LoadFileSection( cmd, arg, SYSPH_MAP_STR, fr, LoadPhraseFromFile) == 0); SavePhraseToFile(fw, 1); /* 1 for system */ fclose(fw); if (!cmd[0] || !arg[0] || strcasecmp(cmd, USRPH_MAP_STR)) return 0; strcat(filename, ".usr"); if ( (fw = fopen(filename,"w"))==NULL) print_error("Failed to create pinyin user phrase output file %s", filename); for(i = 0; i < MAX_PY_NUM; i++) { phtab[i] = NULL; phcount[i] = 0; } while(LoadFileSection(cmd, arg, USRPH_MAP_STR, fr, LoadPhraseFromFile) == 0) { cmd_arg(fr,LineBuf, &cmd, &arg); } SavePhraseToFile(fw, 0); /* 0 for user */ fclose(fw); fclose(fr); return 0; }