1/*
2 * Copyright (C) 2008,2009  OMRON SOFTWARE Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "nj_lib.h"
18#include "nj_err.h"
19#include "nj_ext.h"
20#include "nj_dic.h"
21#include "njd.h"
22#ifdef NJ_LEARN_MUHENKAN_DEBUG
23#include <stdio.h>
24#include <def_mojicode.h>
25#endif
26#ifdef NJ_AWNN22_DEBUG
27#include <stdio.h>
28#include <def_mojicode.h>
29#endif
30
31#define QUE_TYPE_EMPTY  0
32#define QUE_TYPE_NEXT   0
33#define QUE_TYPE_JIRI   1
34#define QUE_TYPE_FZK    2
35#define POS_DATA_OFFSET  0x20
36#define POS_LEARN_WORD   0x24
37#define POS_MAX_WORD     0x28
38#define POS_QUE_SIZE     0x2C
39#define POS_NEXT_QUE     0x30
40#define POS_WRITE_FLG    0x34
41#define POS_INDEX_OFFSET        0x3C
42#define POS_INDEX_OFFSET2       0x40
43
44#define LEARN_INDEX_TOP_ADDR(x) ((x) + (NJ_INT32_READ((x) + POS_INDEX_OFFSET)))
45#define LEARN_INDEX_TOP_ADDR2(x) ((x) + (NJ_INT32_READ((x) + POS_INDEX_OFFSET2)))
46#define LEARN_DATA_TOP_ADDR(x)  ((x) + (NJ_INT32_READ((x) + POS_DATA_OFFSET)))
47
48#define LEARN_INDEX_BOTTOM_ADDR(x) (LEARN_DATA_TOP_ADDR(x) - 1)
49
50#define LEARN_QUE_STRING_OFFSET 5
51
52#define ADDRESS_TO_POS(x,adr)   (((adr) - LEARN_DATA_TOP_ADDR(x)) / QUE_SIZE(x))
53#define POS_TO_ADDRESS(x,pos)   (LEARN_DATA_TOP_ADDR(x) + QUE_SIZE(x) * (pos))
54
55#define GET_UINT16(ptr) ((((NJ_UINT16)(*(ptr))) << 8) | (*((ptr) + 1) & 0x00ff))
56
57#define GET_FPOS_FROM_DATA(x) ((NJ_UINT16)NJ_INT16_READ((x)+1) >> 7)
58#define GET_YSIZE_FROM_DATA(x) ((NJ_UINT8)((NJ_UINT16)NJ_INT16_READ((x)+1) & 0x7F))
59#define GET_BPOS_FROM_DATA(x) ((NJ_UINT16)NJ_INT16_READ((x)+3) >> 7)
60#define GET_KSIZE_FROM_DATA(x) ((NJ_UINT8)((NJ_UINT16)NJ_INT16_READ((x)+3) & 0x7F))
61#define GET_BPOS_FROM_EXT_DATA(x) ((NJ_UINT16)NJ_INT16_READ(x) >> 7)
62#define GET_YSIZE_FROM_EXT_DATA(x) ((NJ_UINT8)((NJ_UINT16)NJ_INT16_READ(x) & 0x7F))
63
64#define SET_BPOS_AND_YSIZE(x,bpos,ysize)                                \
65    NJ_INT16_WRITE((x), ((NJ_UINT16)((bpos) << 7) | ((ysize) & 0x7F)))
66#define SET_FPOS_AND_YSIZE(x,fpos,ysize)                                \
67    NJ_INT16_WRITE(((x)+1), ((NJ_UINT16)((fpos) << 7) | ((ysize) & 0x7F)))
68#define SET_BPOS_AND_KSIZE(x,bpos,ksize)                                \
69    NJ_INT16_WRITE(((x)+3), ((NJ_UINT16)((bpos) << 7) | ((ksize) & 0x7F)))
70
71#define GET_TYPE_FROM_DATA(x) (*(x) & 0x03)
72#define GET_UFLG_FROM_DATA(x) (*(x) >> 7)
73#define GET_FFLG_FROM_DATA(x) ((*(x) >> 6) & 0x01)
74#define GET_MFLG_FROM_DATA(x) (*(x) & 0x10)
75
76#define SET_TYPE_UFLG_FFLG(x,type,u,f)                                  \
77    (*(x) = (NJ_UINT8)(((type) & 0x03) |                                \
78                       (((u) & 0x01) << 7) | (((f) & 0x01) << 6)))
79#define SET_TYPE_ALLFLG(x,type,u,f,m)                                   \
80    (*(x) = (NJ_UINT8)(((type) & 0x03) |                                \
81                       (((u) & 0x01) << 7) | (((f) & 0x01) << 6) | (((m) & 0x01) << 4)))
82
83#define RESET_FFLG(x) (*(x) &= 0xbf)
84
85#define STATE_COPY(to, from)                                    \
86    { ((NJ_UINT8*)(to))[0] = ((NJ_UINT8*)(from))[0];            \
87        ((NJ_UINT8*)(to))[1] = ((NJ_UINT8*)(from))[1];          \
88        ((NJ_UINT8*)(to))[2] = ((NJ_UINT8*)(from))[2];          \
89        ((NJ_UINT8*)(to))[3] = ((NJ_UINT8*)(from))[3]; }
90
91#define USE_QUE_NUM(que_size, str_size)    \
92    ( (((str_size) % ((que_size) - 1)) == 0)                           \
93      ? ((str_size) / ((que_size) - 1))                                \
94      : ((str_size) / ((que_size) - 1) + 1) )
95
96#define NEXT_QUE(que, max)  ( ((que) < ((max) - 1)) ? ((que) + 1) : 0 )
97
98#define PREV_QUE(que, max)  ( ((que) == 0) ? ((max) - 1) : ((que) - 1) )
99
100#define COPY_QUE(handle, src, dst)                                      \
101    nj_memcpy(POS_TO_ADDRESS((handle), (dst)), POS_TO_ADDRESS((handle), (src)), QUE_SIZE(handle))
102
103
104#define INIT_HINDO          (-10000)
105
106#define LOC_CURRENT_NO_ENTRY  0xffffffffU
107
108
109
110static NJ_WQUE *get_que(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id);
111static NJ_INT16 is_continued(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id);
112static NJ_UINT16 search_next_que(NJ_DIC_HANDLE handle, NJ_UINT16 que_id);
113static NJ_INT16 que_strcmp_complete_with_hyouki(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id, NJ_CHAR *yomi, NJ_UINT16 yomi_len, NJ_CHAR *hyouki, NJ_UINT8 multi_flg);
114static NJ_CHAR  *get_string(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id, NJ_UINT8 *slen);
115static NJ_CHAR  *get_hyouki(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id, NJ_UINT8 *slen);
116static NJ_INT16 get_cand_by_sequential(NJ_CLASS *iwnn, NJ_SEARCH_CONDITION *cond, NJ_SEARCH_LOCATION_SET *loctset, NJ_UINT8 search_pattern, NJ_UINT8 comp_flg);
117static NJ_INT16 get_cand_by_evaluate(NJ_CLASS *iwnn, NJ_SEARCH_CONDITION *cond, NJ_SEARCH_LOCATION_SET *loctset, NJ_UINT8 search_pattern);
118static NJ_INT16 get_cand_by_evaluate2(NJ_CLASS *iwnn, NJ_SEARCH_CONDITION *cond, NJ_SEARCH_LOCATION_SET *loctset, NJ_UINT8 search_pattern, NJ_UINT16 hIdx);
119static NJ_INT16 search_range_by_yomi(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT8 op, NJ_CHAR *yomi, NJ_UINT16 ylen, NJ_UINT16 *from, NJ_UINT16 *to, NJ_UINT8 *forward_flag);
120static NJ_INT16 search_range_by_yomi2(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT8 op, NJ_CHAR *yomi, NJ_UINT16 ylen, NJ_UINT16 sfrom, NJ_UINT16 sto, NJ_UINT16 *from, NJ_UINT16 *to,
121                                      NJ_UINT8 *forward_flag);
122static NJ_INT16 search_range_by_yomi_multi(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_CHAR *yomi, NJ_UINT16 ylen, NJ_UINT16 *from, NJ_UINT16 *to);
123static NJ_INT16 str_que_cmp(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_CHAR *yomi, NJ_UINT16 yomiLen, NJ_UINT16 que_id, NJ_UINT8 mode);
124static NJ_WQUE *get_que_type_and_next(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id);
125static NJ_WQUE *get_que_allHinsi(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id);
126static NJ_WQUE *get_que_yomiLen_and_hyoukiLen(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id);
127static NJ_INT16 continue_cnt(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id);
128
129static NJ_UINT8 *get_search_index_address(NJ_DIC_HANDLE handle, NJ_UINT8 search_pattern);
130
131static NJ_HINDO get_hindo(NJ_CLASS *iwnn, NJ_SEARCH_LOCATION_SET *loctset, NJ_UINT8 search_pattern);
132
133static NJ_HINDO calculate_hindo(NJ_DIC_HANDLE handle, NJ_INT32 freq, NJ_DIC_FREQ *dic_freq, NJ_INT16 freq_max, NJ_INT16 freq_min);
134static NJ_INT16 que_strcmp_include(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id, NJ_CHAR *yomi);
135
136#define GET_LEARN_MAX_WORD_COUNT(h) ((NJ_UINT16)NJ_INT32_READ((h) + POS_MAX_WORD))
137
138#define GET_LEARN_WORD_COUNT(h)                         \
139    ((NJ_UINT16)NJ_INT32_READ((h) + POS_LEARN_WORD))
140#define SET_LEARN_WORD_COUNT(h, n)                      \
141    NJ_INT32_WRITE((h)+POS_LEARN_WORD, (NJ_UINT32)(n))
142#define GET_LEARN_NEXT_WORD_POS(h)                      \
143    ((NJ_UINT16)NJ_INT32_READ((h) + POS_NEXT_QUE))
144#define SET_LEARN_NEXT_WORD_POS(h, id)                  \
145    NJ_INT32_WRITE((h)+POS_NEXT_QUE, (NJ_UINT32)(id))
146#define QUE_SIZE(h)     ((NJ_UINT16)NJ_INT32_READ((h) + POS_QUE_SIZE))
147
148#define COPY_UINT16(dst,src)    (*(NJ_UINT16 *)(dst) = *(NJ_UINT16 *)(src))
149
150static NJ_UINT8 *get_search_index_address(NJ_DIC_HANDLE handle, NJ_UINT8 search_pattern) {
151
152
153
154    return LEARN_INDEX_TOP_ADDR(handle);
155}
156
157NJ_INT16 njd_l_search_word(NJ_CLASS *iwnn, NJ_SEARCH_CONDITION *con,
158                           NJ_SEARCH_LOCATION_SET *loctset,
159                           NJ_UINT8 comp_flg) {
160
161    NJ_UINT16    word_count;
162    NJ_UINT32    type;
163    NJ_DIC_INFO *pdicinfo;
164    NJ_UINT16    hIdx;
165    NJ_INT16     ret;
166
167
168    word_count = GET_LEARN_WORD_COUNT(loctset->loct.handle);
169    if (word_count == 0) {
170
171        loctset->loct.status = NJ_ST_SEARCH_END_EXT;
172        return 0;
173    }
174
175    type = NJ_GET_DIC_TYPE_EX(loctset->loct.type, loctset->loct.handle);
176
177    if (type == NJ_DIC_TYPE_CUSTOM_INCOMPRESS) {
178        if ((con->operation == NJ_CUR_OP_COMP) ||
179            (con->operation == NJ_CUR_OP_FORE)){
180
181            if (con->ylen > NJ_GET_MAX_YLEN(loctset->loct.handle)) {
182                loctset->loct.status = NJ_ST_SEARCH_END_EXT;
183                return 0;
184            }
185        }
186    }
187
188
189    switch (con->operation) {
190    case NJ_CUR_OP_COMP:
191        if (con->mode != NJ_CUR_MODE_FREQ) {
192
193            loctset->loct.status = NJ_ST_SEARCH_END_EXT;
194            break;
195        }
196
197
198        return get_cand_by_sequential(iwnn, con, loctset, con->operation, comp_flg);
199
200    case NJ_CUR_OP_FORE:
201
202        if (con->mode == NJ_CUR_MODE_YOMI) {
203
204            return get_cand_by_sequential(iwnn, con, loctset, con->operation, 0);
205        } else {
206
207
208            pdicinfo = con->ds->dic;
209            for (hIdx = 0; (hIdx < NJ_MAX_DIC) && (pdicinfo->handle != loctset->loct.handle); hIdx++) {
210                pdicinfo++;
211            }
212
213            if (hIdx == NJ_MAX_DIC) {
214
215                loctset->loct.status = NJ_ST_SEARCH_END;
216                return 0;
217            }
218
219
220
221            if ((con->ds->dic[hIdx].srhCache == NULL) || (con->ylen == 0) ||
222                !(con->ds->mode & 0x0001)) {
223                return get_cand_by_evaluate(iwnn, con, loctset, con->operation);
224            } else {
225                ret = get_cand_by_evaluate2(iwnn, con, loctset, con->operation, hIdx);
226                if (ret == NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_CACHE_NOT_ENOUGH)) {
227
228                    NJ_SET_CACHEOVER_TO_SCACHE(con->ds->dic[hIdx].srhCache);
229                    ret = get_cand_by_evaluate2(iwnn, con, loctset, con->operation, hIdx);
230                }
231                return ret;
232            }
233        }
234
235    case NJ_CUR_OP_LINK:
236
237        if (NJ_GET_DIC_TYPE_EX(loctset->loct.type, loctset->loct.handle) == NJ_DIC_TYPE_USER) {
238
239            loctset->loct.status = NJ_ST_SEARCH_END_EXT;
240            break;
241        }
242        if (con->mode != NJ_CUR_MODE_FREQ) {
243
244            loctset->loct.status = NJ_ST_SEARCH_END_EXT;
245            break;
246        }
247
248        if (comp_flg == 0) {
249
250            return get_cand_by_sequential(iwnn, con, loctset, con->operation, 0);
251        } else {
252
253            return get_cand_by_evaluate(iwnn, con, loctset, con->operation);
254        }
255
256    default:
257        loctset->loct.status = NJ_ST_SEARCH_END_EXT;
258    }
259
260    return 0;
261}
262
263static NJ_WQUE *get_que_type_and_next(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle,
264                                      NJ_UINT16 que_id) {
265    NJ_UINT8 *ptr;
266    NJ_WQUE *que = &(iwnn->que_tmp);
267
268
269    if (que_id >= GET_LEARN_MAX_WORD_COUNT(handle)) {
270        return NULL;
271    }
272
273    ptr = POS_TO_ADDRESS(handle, que_id);
274
275    que->type = GET_TYPE_FROM_DATA(ptr);
276    que->next_flag  = GET_FFLG_FROM_DATA(ptr);
277
278    switch (que->type) {
279    case QUE_TYPE_EMPTY:
280    case QUE_TYPE_JIRI:
281    case QUE_TYPE_FZK:
282        return que;
283    default:
284        break;
285    }
286#ifdef LEARN_DEBUG
287    printf("FATAL : Illegal que was gotten (que_id=%d)\n", que_id);
288#endif
289    return NULL;
290}
291
292static NJ_WQUE *get_que_yomiLen_and_hyoukiLen(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle,
293                                              NJ_UINT16 que_id) {
294    NJ_UINT8 *ptr;
295    NJ_WQUE *que = &(iwnn->que_tmp);
296
297
298    if (que_id >= GET_LEARN_MAX_WORD_COUNT(handle)) {
299        return NULL;
300    }
301
302    ptr = POS_TO_ADDRESS(handle, que_id);
303
304    que->type        = GET_TYPE_FROM_DATA(ptr);
305    que->yomi_byte   = GET_YSIZE_FROM_DATA(ptr);
306    que->yomi_len    = que->yomi_byte / sizeof(NJ_CHAR);
307    que->hyouki_byte = GET_KSIZE_FROM_DATA(ptr);
308    que->hyouki_len  = que->hyouki_byte / sizeof(NJ_CHAR);
309
310    switch (que->type) {
311    case QUE_TYPE_JIRI:
312    case QUE_TYPE_FZK:
313        return que;
314    default:
315        break;
316    }
317#ifdef LEARN_DEBUG
318    printf("FATAL : Illegal que was gotten (que_id=%d)\n", que_id);
319#endif
320    return NULL;
321}
322
323static NJ_WQUE *get_que_allHinsi(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle,
324                                 NJ_UINT16 que_id) {
325    NJ_UINT8 *ptr;
326    NJ_WQUE *que = &(iwnn->que_tmp);
327
328
329    if (que_id >= GET_LEARN_MAX_WORD_COUNT(handle)) {
330        return NULL;
331    }
332
333    ptr = POS_TO_ADDRESS(handle, que_id);
334
335    que->type      = GET_TYPE_FROM_DATA(ptr);
336    que->mae_hinsi = GET_FPOS_FROM_DATA(ptr);
337    que->ato_hinsi = GET_BPOS_FROM_DATA(ptr);
338
339    switch (que->type) {
340    case QUE_TYPE_JIRI:
341    case QUE_TYPE_FZK:
342        return que;
343    default:
344        break;
345    }
346#ifdef LEARN_DEBUG
347    printf("FATAL : Illegal que was gotten (que_id=%d)\n", que_id);
348#endif
349    return NULL;
350}
351
352static NJ_WQUE *get_que(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id) {
353    NJ_UINT8 *ptr;
354    NJ_WQUE *que = &(iwnn->que_tmp);
355
356
357    if (que_id >= GET_LEARN_MAX_WORD_COUNT(handle)) {
358        return NULL;
359    }
360
361    ptr = POS_TO_ADDRESS(handle, que_id);
362
363    que->entry      = que_id;
364    que->type       = GET_TYPE_FROM_DATA(ptr);
365    que->mae_hinsi  = GET_FPOS_FROM_DATA(ptr);
366    que->ato_hinsi  = GET_BPOS_FROM_DATA(ptr);
367    que->yomi_byte  = GET_YSIZE_FROM_DATA(ptr);
368    que->yomi_len   = que->yomi_byte / sizeof(NJ_CHAR);
369    que->hyouki_byte= GET_KSIZE_FROM_DATA(ptr);
370    que->hyouki_len = que->hyouki_byte / sizeof(NJ_CHAR);
371    que->next_flag  = GET_FFLG_FROM_DATA(ptr);
372
373    switch (que->type) {
374    case QUE_TYPE_JIRI:
375    case QUE_TYPE_FZK:
376        return que;
377    default:
378        break;
379    }
380#ifdef LEARN_DEBUG
381    printf("FATAL : Illegal que was gotten (que_id=%d)\n", que_id);
382#endif
383    return NULL;
384}
385
386static NJ_INT16 is_continued(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id) {
387    NJ_WQUE *que;
388    NJ_UINT16 i;
389    NJ_UINT16 max, end;
390
391
392    max = GET_LEARN_MAX_WORD_COUNT(handle);
393    end = GET_LEARN_NEXT_WORD_POS(handle);
394
395    for (i = 0; i < max; i++) {
396        que_id++;
397        if (que_id >= GET_LEARN_MAX_WORD_COUNT(handle)) {
398
399            que_id = 0;
400        }
401
402
403        if (que_id == end) {
404
405            return 0;
406        }
407
408        que = get_que_type_and_next(iwnn, handle, que_id);
409#ifdef IWNN_ERR_CHECK
410        if (iwnn->err_check_flg == 1) {
411            que = NULL;
412        }
413#endif
414        if (que == NULL) {
415            return NJ_SET_ERR_VAL(NJ_FUNC_IS_CONTINUED, NJ_ERR_DIC_BROKEN);
416        }
417        if (que->type != QUE_TYPE_EMPTY) {
418
419            if (que->next_flag != 0) {
420
421                return 1;
422            } else {
423
424                return 0;
425            }
426        }
427    }
428
429
430    return 0;
431}
432
433static NJ_INT16 continue_cnt(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT16 que_id) {
434    NJ_WQUE *que;
435    NJ_UINT16 i;
436    NJ_UINT16 max, end;
437    NJ_INT16 cnt = 0;
438
439
440    max = GET_LEARN_MAX_WORD_COUNT(handle);
441    end = GET_LEARN_NEXT_WORD_POS(handle);
442
443    for (i = 0; i < max; i++) {
444        que_id++;
445        if (que_id >= max) {
446
447            que_id = 0;
448        }
449
450
451        if (que_id == end) {
452
453            return cnt;
454        }
455
456        que = get_que_type_and_next(iwnn, handle, que_id);
457        if (que == NULL) {
458            return NJ_SET_ERR_VAL(NJ_FUNC_CONTINUE_CNT, NJ_ERR_DIC_BROKEN);
459        }
460        if (que->type != QUE_TYPE_EMPTY) {
461
462            if (que->next_flag != 0) {
463
464                cnt++;
465
466
467                if (cnt >= (NJD_MAX_CONNECT_CNT - 1)) {
468                    return cnt;
469                }
470            } else {
471
472                return cnt;
473            }
474        }
475    }
476
477
478    return 0;
479}
480
481static NJ_UINT16 search_next_que(NJ_DIC_HANDLE handle, NJ_UINT16 que_id) {
482    NJ_UINT16 max;
483    NJ_UINT16 i;
484
485
486    max = GET_LEARN_MAX_WORD_COUNT(handle);
487
488    for (i = 0; i < max; i++) {
489        que_id++;
490        if (que_id >= max) {
491
492            que_id = 0;
493        }
494
495        if (GET_TYPE_FROM_DATA(POS_TO_ADDRESS(handle, que_id)) != QUE_TYPE_EMPTY) {
496
497            return que_id;
498        }
499    }
500
501
502    return 0;
503}
504
505static NJ_INT16 que_strcmp_complete_with_hyouki(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle,
506                                                NJ_UINT16 que_id, NJ_CHAR *yomi, NJ_UINT16 yomi_len, NJ_CHAR *hyouki,
507                                                NJ_UINT8 multi_flg) {
508    NJ_CHAR *str;
509    NJ_INT16 ret;
510    NJ_UINT8 slen;
511    NJ_UINT16 hyouki_len;
512    NJ_UINT16 que_yomilen, que_hyoukilen;
513    NJ_INT16 que_count = 1;
514    NJ_INT16 cnt = 0;
515
516
517
518    hyouki_len = nj_strlen(hyouki);
519
520    if (multi_flg == 0) {
521
522        cnt = 1;
523    } else {
524
525
526        cnt = GET_LEARN_WORD_COUNT(handle);
527    }
528
529    while (cnt--) {
530        str = get_string(iwnn, handle, que_id, &slen);
531        if (str == NULL) {
532            return NJ_SET_ERR_VAL(NJ_FUNC_QUE_STRCMP_COMPLETE_WITH_HYOUKI,
533                                  NJ_ERR_DIC_BROKEN);
534        }
535        que_yomilen = slen;
536
537        ret = nj_strncmp(yomi, str, que_yomilen);
538        if (ret != 0) {
539
540            return 0;
541        }
542
543        str = get_hyouki(iwnn, handle, que_id, &slen);
544        if (str == NULL) {
545            return NJ_SET_ERR_VAL(NJ_FUNC_QUE_STRCMP_COMPLETE_WITH_HYOUKI,
546                                  NJ_ERR_DIC_BROKEN);
547        }
548        que_hyoukilen = slen;
549
550        ret = nj_strncmp(hyouki, str, que_hyoukilen);
551        if (ret != 0) {
552
553            return 0;
554        }
555
556        if ((yomi_len == que_yomilen) &&
557            (hyouki_len == que_hyoukilen)) {
558
559            return que_count;
560        }
561
562        if ((que_yomilen > yomi_len) ||
563            (que_hyoukilen > hyouki_len)) {
564
565            return 0;
566        }
567
568        ret = is_continued(iwnn, handle, que_id);
569        if (ret <= 0) {
570
571            return ret;
572        }
573
574
575        if (que_count >= (NJD_MAX_CONNECT_CNT - 1)) {
576
577            return 0;
578        }
579
580        yomi_len -= que_yomilen;
581        yomi     += que_yomilen;
582
583        hyouki_len -= que_hyoukilen;
584        hyouki     += que_hyoukilen;
585
586
587        que_id = search_next_que(handle, que_id);
588        que_count++;
589    }
590    return 0;
591}
592
593static NJ_INT16 que_strcmp_include(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle,
594                                   NJ_UINT16 que_id, NJ_CHAR *yomi) {
595    NJ_CHAR *str;
596    NJ_UINT16 que_len;
597    NJ_UINT16 yomi_len;
598    NJ_INT16 ret;
599    NJ_INT16 que_count = 1;
600    NJ_UINT16 i = 0;
601    NJ_UINT8 slen;
602
603
604#ifdef LEARN_DEBUG
605    printf("que_strcmp_include(que_id=%d, yomi=[%s])\n", que_id, yomi);
606#endif
607    yomi_len = nj_strlen(yomi);
608    if (yomi_len == 0) {
609        return que_count;
610    }
611
612    i = GET_LEARN_WORD_COUNT(handle);
613
614    while (--i) {
615
616
617        ret = is_continued(iwnn, handle, que_id);
618        if (ret < 0) {
619
620            return ret;
621        } else if (ret == 0) {
622
623            return que_count;
624        }
625
626
627        que_id = search_next_que(handle, que_id);
628
629        str = get_string(iwnn, handle, que_id, &slen);
630#ifdef IWNN_ERR_CHECK
631        if (iwnn->err_check_flg == 2) {
632            str = NULL;
633        }
634#endif
635        if (str == NULL) {
636            return NJ_SET_ERR_VAL(NJ_FUNC_QUE_STRCMP_INCLUDE, NJ_ERR_DIC_BROKEN);
637        }
638        que_len = slen;
639
640
641        if (que_len > yomi_len) {
642#ifdef LEARN_DEBUG
643            printf("  >> mismatch [%s] (que_len > yomi_len)\n", str);
644#endif
645            return que_count;
646        }
647
648
649        ret = nj_strncmp(yomi, str, que_len);
650        if (ret != 0) {
651#ifdef LEARN_DEBUG
652            printf("  >> mismatch [%s]\n", str);
653#endif
654
655            return que_count;
656        }
657
658
659        if (que_len == yomi_len) {
660#ifdef LEARN_DEBUG
661            printf("  >> match! [%s](%d)\n", str, que_count);
662#endif
663            return (que_count + 1);
664        }
665
666        que_count++;
667        if (que_count >= NJD_MAX_CONNECT_CNT) {
668
669            return que_count;
670        }
671
672
673        yomi_len -= que_len;
674        yomi     += que_len;
675    }
676
677    return que_count;
678}
679
680static NJ_CHAR *get_string(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle,
681                           NJ_UINT16 que_id, NJ_UINT8 *slen) {
682    NJ_UINT8 *src, *dst;
683    NJ_UINT8 copy_size, size;
684    NJ_UINT8 i;
685    NJ_UINT8 *top_addr;
686    NJ_UINT8 *bottom_addr;
687    NJ_UINT16 que_size;
688
689
690    src = POS_TO_ADDRESS(handle, que_id);
691    switch (GET_TYPE_FROM_DATA(src)) {
692    case QUE_TYPE_JIRI:
693    case QUE_TYPE_FZK:
694        size =  GET_YSIZE_FROM_DATA(src);
695        *slen = (NJ_UINT8)(size / sizeof(NJ_CHAR));
696        break;
697
698    default:
699#ifdef LEARN_DEBUG
700        printf("get_string(handle=%p, que_id=%d) : broken que\n", handle, que_id);
701#endif
702        return NULL;
703    }
704
705    if (NJ_GET_DIC_TYPE(handle) == NJ_DIC_TYPE_USER) {
706        if (*slen > NJ_MAX_USER_LEN) {
707            return NULL;
708        }
709    } else {
710        if (*slen > NJ_MAX_LEN) {
711            return NULL;
712        }
713    }
714
715
716    src += LEARN_QUE_STRING_OFFSET;
717
718    que_size = QUE_SIZE(handle);
719
720
721    copy_size = (NJ_UINT8)que_size - LEARN_QUE_STRING_OFFSET;
722    dst = (NJ_UINT8*)&(iwnn->learn_string_tmp[0]);
723    if (copy_size > size) {
724
725        copy_size = size;
726    }
727    for (i = 0; i < copy_size; i++) {
728        *dst++ = *src++;
729    }
730
731
732    top_addr = LEARN_DATA_TOP_ADDR(handle);
733    bottom_addr = top_addr;
734    bottom_addr += que_size * GET_LEARN_MAX_WORD_COUNT(handle) - 1;
735
736    while (size -= copy_size) {
737
738        if (src >= bottom_addr) {
739            src = top_addr;
740        }
741
742
743        if (*src != QUE_TYPE_NEXT) {
744#ifdef LEARN_DEBUG
745            printf("FATAL: src que was broken(not QUE_TYPE_NEXT) [src=%x]\n", src);
746#endif
747            return NULL;
748        }
749
750        src++;
751        if (size < que_size) {
752
753            copy_size = size;
754        } else {
755            copy_size = (NJ_UINT8)(que_size - 1);
756        }
757        for (i = 0; i < copy_size; i++) {
758            *dst++ = *src++;
759        }
760    }
761    iwnn->learn_string_tmp[*slen] = NJ_CHAR_NUL;
762
763    return &(iwnn->learn_string_tmp[0]);
764}
765
766static NJ_CHAR *get_hyouki(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle,
767                           NJ_UINT16 que_id, NJ_UINT8 *slen) {
768    NJ_UINT8 *src, *dst;
769    NJ_WQUE *que;
770    NJ_UINT8 copy_size, size;
771    NJ_UINT8 i;
772    NJ_UINT8 *top_addr;
773    NJ_UINT8 *bottom_addr;
774    NJ_CHAR  *hira;
775    NJ_UINT16 que_size;
776    NJ_UINT32 dictype;
777
778
779    que = get_que_yomiLen_and_hyoukiLen(iwnn, handle, que_id);
780    if (que == NULL) {
781        return NULL;
782    }
783
784    dictype = NJ_GET_DIC_TYPE(handle);
785    if (dictype == NJ_DIC_TYPE_USER) {
786        if (que->yomi_len > NJ_MAX_USER_LEN) {
787            return NULL;
788        }
789        if (que->hyouki_len > NJ_MAX_USER_KOUHO_LEN) {
790            return NULL;
791        }
792    } else {
793        if (que->yomi_len > NJ_MAX_LEN) {
794            return NULL;
795        }
796        if (que->hyouki_len > NJ_MAX_RESULT_LEN) {
797            return NULL;
798        }
799    }
800
801    src = POS_TO_ADDRESS(handle, que_id);
802
803    if (que->hyouki_len == 0) {
804        hira = get_string(iwnn, handle, que_id, slen);
805        if (hira == NULL) {
806            return NULL;
807        }
808
809        if (GET_MFLG_FROM_DATA(src) != 0) {
810            *slen = (NJ_UINT8)nje_convert_hira_to_kata(hira, &(iwnn->muhenkan_tmp[0]), *slen);
811            return &(iwnn->muhenkan_tmp[0]);
812        } else {
813            return hira;
814        }
815    }
816
817    src += LEARN_QUE_STRING_OFFSET;
818
819    que_size = QUE_SIZE(handle);
820
821
822    size = que->yomi_byte;
823    copy_size = (NJ_UINT8)que_size - LEARN_QUE_STRING_OFFSET;
824    dst = (NJ_UINT8*)&(iwnn->learn_string_tmp[0]);
825    if (copy_size > size) {
826
827        copy_size = size;
828    }
829
830
831    top_addr = LEARN_DATA_TOP_ADDR(handle);
832    bottom_addr = top_addr;
833    bottom_addr += que_size * GET_LEARN_MAX_WORD_COUNT(handle) - 1;
834
835    src += copy_size;
836    while (size -= copy_size) {
837
838
839        if (src >= bottom_addr) {
840            src = top_addr;
841        }
842
843
844        if (*src != QUE_TYPE_NEXT) {
845#ifdef LEARN_DEBUG
846            printf("FATAL: src que was broken(not QUE_TYPE_NEXT) [src=%x]\n", src);
847#endif
848            return NULL;
849        }
850
851        src++;
852        if (size < que_size) {
853
854            copy_size = size;
855        } else {
856            copy_size = (NJ_UINT8)(que_size - 1);
857        }
858        src += copy_size;
859    }
860
861
862
863    if (((src - top_addr) % que_size) == 0) {
864
865        if (src >= bottom_addr) {
866            src = top_addr;
867        }
868
869        if (*src++ != QUE_TYPE_NEXT) {
870#ifdef LEARN_DEBUG
871            printf("FATAL: src que was broken(QUE_TYPE_NEXT) [src=%x]\n", src - 1);
872#endif
873            return NULL;
874        }
875    }
876
877    size = que->hyouki_byte;
878
879
880    copy_size = (NJ_UINT8)(que_size);
881    copy_size -= (NJ_UINT8)((src - top_addr) % que_size);
882    if (copy_size > size) {
883
884        copy_size = size;
885    }
886    for (i = 0; i < copy_size; i++) {
887        *dst++ = *src++;
888    }
889
890    while (size -= copy_size) {
891
892
893        if (src >= bottom_addr) {
894            src = top_addr;
895        }
896
897
898        if (*src != QUE_TYPE_NEXT) {
899#ifdef LEARN_DEBUG
900            printf("FATAL: src que was broken(not QUE_TYPE_NEXT) [src=%x]\n", src);
901#endif
902            return NULL;
903        }
904
905        src++;
906        if (size < que_size) {
907
908            copy_size = size;
909        } else {
910            copy_size = (NJ_UINT8)(que_size - 1);
911        }
912
913        for (i = 0; i < copy_size; i++) {
914            *dst++ = *src++;
915        }
916    }
917
918    *slen = que->hyouki_len;
919    iwnn->learn_string_tmp[*slen] = NJ_CHAR_NUL;
920
921    return &(iwnn->learn_string_tmp[0]);
922}
923
924static NJ_INT16 get_cand_by_sequential(NJ_CLASS *iwnn, NJ_SEARCH_CONDITION *cond,
925                                       NJ_SEARCH_LOCATION_SET *loctset, NJ_UINT8 search_pattern,
926                                       NJ_UINT8 comp_flg) {
927    NJ_UINT16 current, from, to;
928    NJ_UINT16 que_id;
929    NJ_UINT8  *ptr, *p;
930    NJ_INT16 ret, num_count;
931    NJ_CHAR  *yomi;
932    NJ_WQUE  *que;
933    NJ_UINT8 forward_flag = 0;
934
935
936
937    if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_NO_INIT) {
938
939        ret = search_range_by_yomi(iwnn, loctset->loct.handle, search_pattern,
940                                   cond->yomi, cond->ylen, &from, &to, &forward_flag);
941        if (ret < 0) {
942            return ret;
943        }
944        if (ret == 0) {
945            if (forward_flag) {
946                loctset->loct.status = NJ_ST_SEARCH_END;
947            } else {
948                loctset->loct.status = NJ_ST_SEARCH_END_EXT;
949            }
950            return 0;
951        }
952        loctset->loct.top = from;
953        loctset->loct.bottom = to;
954        current = from;
955    } else if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_READY) {
956
957        current = (NJ_UINT16)(loctset->loct.current + 1);
958    } else {
959        loctset->loct.status = NJ_ST_SEARCH_END;
960        return 0;
961    }
962
963
964    ptr = get_search_index_address(loctset->loct.handle, cond->operation);
965    p = ptr + (current * NJ_INDEX_SIZE);
966
967    while (current <= loctset->loct.bottom) {
968        que_id = GET_UINT16(p);
969        if (search_pattern == NJ_CUR_OP_COMP) {
970
971            ret = str_que_cmp(iwnn, loctset->loct.handle, cond->yomi, cond->ylen, que_id, 1);
972
973
974            if (ret == 2) {
975                ret = 0;
976            }
977        } else if (search_pattern == NJ_CUR_OP_FORE) {
978
979            ret = str_que_cmp(iwnn, loctset->loct.handle, cond->yomi, cond->ylen, que_id, 2);
980
981
982            if (ret == 2) {
983                ret = 0;
984            }
985        } else {
986
987
988
989            ret = que_strcmp_complete_with_hyouki(iwnn, loctset->loct.handle, que_id,
990                                                  cond->yomi, cond->ylen, cond->kanji, 0);
991        }
992
993        if (ret < 0) {
994            return ret;
995        }
996        if (ret > 0) {
997            if (search_pattern == NJ_CUR_OP_LINK) {
998
999
1000                num_count = continue_cnt(iwnn, loctset->loct.handle, que_id);
1001                if (num_count < 0) {
1002
1003                    return num_count;
1004                }
1005
1006
1007                if (num_count >= ret) {
1008
1009                    loctset->loct.current_info = (NJ_UINT8)(((num_count + 1) << 4) | ret);
1010                    loctset->loct.current = current;
1011                    loctset->loct.status = NJ_ST_SEARCH_READY;
1012                    loctset->cache_freq = get_hindo(iwnn, loctset, search_pattern);
1013                    return 1;
1014                }
1015            } else {
1016
1017
1018
1019
1020
1021
1022                que = get_que_allHinsi(iwnn, loctset->loct.handle, que_id);
1023                if (njd_connect_test(cond, que->mae_hinsi, que->ato_hinsi)) {
1024
1025
1026                    switch (NJ_GET_DIC_TYPE_EX(loctset->loct.type, loctset->loct.handle)) {
1027                    case NJ_DIC_TYPE_CUSTOM_INCOMPRESS:
1028                        if ((search_pattern == NJ_CUR_OP_COMP) && (comp_flg == 1)) {
1029                            yomi = cond->yomi + cond->ylen;
1030                            ret = que_strcmp_include(iwnn, loctset->loct.handle, que_id, yomi);
1031                            if (ret < 0) {
1032                                return ret;
1033                            }
1034                        }
1035                        break;
1036                    default:
1037                        break;
1038                    }
1039                    loctset->loct.current = current;
1040                    loctset->loct.status = NJ_ST_SEARCH_READY;
1041
1042                    loctset->loct.current_info = (ret & 0x0f) << 4;
1043                    loctset->cache_freq = get_hindo(iwnn, loctset, search_pattern);
1044                    return 1;
1045                }
1046            }
1047        }
1048        p += NJ_INDEX_SIZE;
1049        current++;
1050    }
1051
1052
1053    loctset->loct.status = NJ_ST_SEARCH_END;
1054    return 0;
1055}
1056
1057static NJ_INT16 get_cand_by_evaluate(NJ_CLASS *iwnn, NJ_SEARCH_CONDITION *cond,
1058                                     NJ_SEARCH_LOCATION_SET *loctset, NJ_UINT8 search_pattern) {
1059    NJ_UINT16 from, to, i;
1060    NJ_UINT16 que_id, oldest;
1061    NJ_UINT32 max_value, eval, current;
1062    NJ_UINT8  *ptr, *p;
1063    NJ_WQUE  *que;
1064    NJ_INT16 ret, num_count;
1065    NJ_INT32 found = 0;
1066    NJ_UINT8 forward_flag = 0;
1067    NJ_INT32 is_first_search, is_better_freq;
1068
1069
1070
1071    ptr = get_search_index_address(loctset->loct.handle, cond->operation);
1072
1073
1074    oldest = GET_LEARN_NEXT_WORD_POS(loctset->loct.handle);
1075
1076
1077    current = 0;
1078    if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_NO_INIT) {
1079        if (search_pattern == NJ_CUR_OP_LINK) {
1080
1081
1082
1083            ret = search_range_by_yomi_multi(iwnn, loctset->loct.handle,
1084                                             cond->yomi, cond->ylen, &from, &to);
1085        } else {
1086
1087
1088            ret = search_range_by_yomi(iwnn, loctset->loct.handle, search_pattern,
1089                                       cond->yomi, cond->ylen, &from, &to, &forward_flag);
1090        }
1091        if (ret <= 0) {
1092            loctset->loct.status = NJ_ST_SEARCH_END;
1093            return ret;
1094        }
1095        loctset->loct.top = from;
1096        loctset->loct.bottom = to;
1097        is_first_search = 1;
1098    } else if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_READY) {
1099        current = GET_UINT16(ptr + (loctset->loct.current * NJ_INDEX_SIZE));
1100        if (current < oldest) {
1101            current += GET_LEARN_MAX_WORD_COUNT(loctset->loct.handle);
1102        }
1103        is_first_search = 0;
1104    } else {
1105        loctset->loct.status = NJ_ST_SEARCH_END;
1106        return 0;
1107    }
1108
1109
1110    max_value = oldest;
1111
1112    p = ptr + (loctset->loct.top * NJ_INDEX_SIZE);
1113    eval = current;
1114    for (i = (NJ_UINT16)loctset->loct.top; i <= (NJ_UINT16)loctset->loct.bottom; i++) {
1115        que_id = GET_UINT16(p);
1116        if (que_id < oldest) {
1117            eval = que_id + GET_LEARN_MAX_WORD_COUNT(loctset->loct.handle);
1118        } else {
1119            eval = que_id;
1120        }
1121#ifdef LEARN_DEBUG
1122        printf("que(%d) : eval = %d\n", que_id, eval);
1123#endif
1124        is_better_freq = ((eval >= max_value) && ((is_first_search) || (eval < current))) ? 1 : 0;
1125
1126        if (is_better_freq) {
1127
1128            if (search_pattern == NJ_CUR_OP_LINK) {
1129
1130                ret = que_strcmp_complete_with_hyouki(iwnn, loctset->loct.handle, que_id,
1131                                                      cond->yomi, cond->ylen, cond->kanji, 1);
1132            } else {
1133
1134                ret = str_que_cmp(iwnn, loctset->loct.handle, cond->yomi, cond->ylen, que_id, 2);
1135
1136                if (ret == 2) {
1137                    ret = 0;
1138                }
1139            }
1140            if (ret < 0) {
1141                return ret;
1142            }
1143            if (ret >= 1) {
1144                if (search_pattern == NJ_CUR_OP_LINK) {
1145
1146
1147                    num_count = continue_cnt(iwnn, loctset->loct.handle, que_id);
1148                    if (num_count < 0) {
1149
1150                        return num_count;
1151                    }
1152
1153
1154                    if (num_count >= ret) {
1155
1156                        loctset->loct.current_info = (NJ_UINT8)(((num_count + 1) << 4) | ret);
1157                        loctset->loct.current = i;
1158                        max_value = eval;
1159                        found = 1;
1160                    }
1161                } else {
1162
1163
1164
1165
1166
1167                    que = get_que_allHinsi(iwnn, loctset->loct.handle, que_id);
1168                    if (njd_connect_test(cond, que->mae_hinsi, que->ato_hinsi)) {
1169
1170                        loctset->loct.current_info = (NJ_UINT8)0x10;
1171                        loctset->loct.current = i;
1172                        max_value = eval;
1173                        found = 1;
1174#ifdef LEARN_DEBUG
1175                        printf("---keep.");
1176#endif
1177                    }
1178                }
1179            }
1180        }
1181        p += NJ_INDEX_SIZE;
1182    }
1183
1184
1185    if (found == 0) {
1186        loctset->loct.status = NJ_ST_SEARCH_END;
1187        return 0;
1188    } else {
1189        loctset->loct.status = NJ_ST_SEARCH_READY;
1190        loctset->cache_freq = get_hindo(iwnn, loctset, search_pattern);
1191        return 1;
1192    }
1193
1194}
1195
1196static NJ_INT16 search_range_by_yomi(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT8 op,
1197                                     NJ_CHAR  *yomi, NJ_UINT16 len, NJ_UINT16 *from, NJ_UINT16 *to,
1198                                     NJ_UINT8 *forward_flag) {
1199    NJ_UINT16 right, mid = 0, left, max;
1200    NJ_UINT16 que_id;
1201    NJ_UINT8  *ptr, *p;
1202    NJ_CHAR  *str;
1203    NJ_INT16 ret = 0;
1204    NJ_INT32 found = 0;
1205    NJ_UINT8 slen;
1206    NJ_INT32 cmp;
1207
1208
1209
1210    ptr = get_search_index_address(handle, op);
1211
1212    max = GET_LEARN_WORD_COUNT(handle);
1213
1214    right = max - 1;
1215    left = 0;
1216
1217#ifdef LEARN_DEBUG
1218    printf("src:[%s]\n", yomi);
1219#endif
1220
1221    *forward_flag = 0;
1222
1223
1224    switch (op) {
1225    case NJ_CUR_OP_COMP:
1226    case NJ_CUR_OP_LINK:
1227    case NJ_CUR_OP_FORE:
1228
1229
1230
1231        break;
1232    default:
1233        return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_PARAM_OPERATION);
1234    }
1235
1236    while (left <= right) {
1237        mid = left + ((right - left) / 2);
1238        p = ptr + (mid * NJ_INDEX_SIZE);
1239        que_id = GET_UINT16(p);
1240        str = get_string(iwnn, handle, que_id, &slen);
1241
1242#ifdef IWNN_ERR_CHECK
1243        if (iwnn->err_check_flg == 3) {
1244            str = NULL;
1245        }
1246#endif
1247        if (str == NULL) {
1248            return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_DIC_BROKEN);
1249        }
1250
1251        ret = nj_strncmp(yomi, str, len);
1252        if (op != NJ_CUR_OP_FORE) {
1253
1254
1255            if (ret == 0) {
1256                if ((*forward_flag == 0) && (len <= (NJ_UINT16)slen)) {
1257
1258                    *forward_flag = 1;
1259                }
1260                if (len > (NJ_UINT16)slen) {
1261                    ret = 1;
1262                } else if (len < (NJ_UINT16)slen) {
1263                    ret = -1;
1264                }
1265            }
1266        }
1267#ifdef LEARN_DEBUG
1268        printf("   [%d][%d][%d]COMPARE:[%s] = %d\n", left, mid, right, str, ret);
1269#endif
1270        if (ret == 0) {
1271
1272            found = 1;
1273            break;
1274        } else if (ret < 0) {
1275
1276            right = mid - 1;
1277            if (mid == 0) {
1278                break;
1279            }
1280        } else {
1281
1282            left = mid + 1;
1283        }
1284    }
1285
1286    if (!found) {
1287        return 0;
1288    }
1289
1290    if (mid == 0) {
1291        *from = mid;
1292    } else {
1293
1294        p = ((mid - 1) * NJ_INDEX_SIZE) + ptr;
1295
1296        for (cmp = mid - 1; cmp >= 0; cmp--) {
1297            que_id = GET_UINT16(p);
1298            str = get_string(iwnn, handle, que_id, &slen);
1299
1300#ifdef IWNN_ERR_CHECK
1301            if (iwnn->err_check_flg == 4) {
1302                str = NULL;
1303            }
1304#endif
1305            if (str == NULL) {
1306                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_DIC_BROKEN);
1307            }
1308
1309            if (op != NJ_CUR_OP_FORE) {
1310                ret = nj_strncmp(yomi, str, len);
1311                if (ret == 0) {
1312                    if (len > (NJ_UINT16)slen) {
1313                        ret = 1;
1314                    } else if (len < (NJ_UINT16)slen) {
1315                        ret = -1;
1316                    }
1317                }
1318                if (ret > 0) {
1319
1320                    break;
1321                }
1322            } else {
1323
1324                if (nj_strncmp(yomi, str, len) != 0) {
1325                    break;
1326                }
1327            }
1328            p -= NJ_INDEX_SIZE;
1329        }
1330        if (cmp < 0) {
1331            *from = 0;
1332        } else {
1333            *from = (NJ_UINT16)cmp + 1;
1334        }
1335    }
1336
1337#ifdef LEARN_DEBUG
1338    printf("  >> from:(%d)\n", *from);
1339#endif
1340
1341#ifdef IWNN_ERR_CHECK
1342    if (iwnn->err_check_flg == 5) {
1343        mid = max - 2;
1344    }
1345#endif
1346    if ((mid + 1) >= max) {
1347        *to = mid;
1348    } else {
1349
1350        p = ((mid + 1) * NJ_INDEX_SIZE) + ptr;
1351
1352        for (right = mid + 1; right < max; right++) {
1353            que_id = GET_UINT16(p);
1354            str = get_string(iwnn, handle, que_id, &slen);
1355
1356#ifdef IWNN_ERR_CHECK
1357            if (iwnn->err_check_flg == 5) {
1358                str = NULL;
1359            }
1360#endif
1361            if (str == NULL) {
1362                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_DIC_BROKEN);
1363            }
1364
1365            if (op != NJ_CUR_OP_FORE) {
1366                ret = nj_strncmp(yomi, str, len);
1367                if (ret == 0) {
1368                    if (len > (NJ_UINT16)slen) {
1369                        ret = 1;
1370                    } else if (len < (NJ_UINT16)slen) {
1371                        ret = -1;
1372                    }
1373                }
1374                if (ret < 0) {
1375
1376                    break;
1377                }
1378            } else {
1379
1380                if (nj_strncmp(yomi, str, len) != 0) {
1381                    break;
1382                }
1383            }
1384            p += NJ_INDEX_SIZE;
1385        }
1386        *to = right - 1;
1387    }
1388
1389#ifdef LEARN_DEBUG
1390    printf("  >> to:(%d)\n", *to);
1391#endif
1392    return 1;
1393}
1394
1395static NJ_INT16 search_range_by_yomi_multi(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle,
1396                                           NJ_CHAR *yomi, NJ_UINT16 len, NJ_UINT16 *from, NJ_UINT16 *to) {
1397    NJ_UINT16 right, mid = 0, left, max = 0;
1398    NJ_UINT16 que_id;
1399    NJ_UINT8  *ptr, *p;
1400    NJ_INT16 ret = 0;
1401    NJ_UINT16 comp_len;
1402    NJ_UINT16 i, char_len;
1403    NJ_INT32 found = 0;
1404    NJ_INT32 cmp;
1405    NJ_CHAR  comp_yomi[NJ_MAX_LEN + NJ_TERM_LEN];
1406    NJ_CHAR  *pYomi;
1407
1408
1409
1410
1411    ptr = LEARN_INDEX_TOP_ADDR(handle);
1412
1413
1414    max = GET_LEARN_WORD_COUNT(handle);
1415
1416#ifdef LEARN_DEBUG
1417    printf("src:[%s]\n", yomi);
1418#endif
1419
1420    comp_len = 0;
1421    pYomi = &yomi[0];
1422    while (comp_len < len) {
1423
1424
1425        char_len = NJ_CHAR_LEN(pYomi);
1426        for (i = 0; i < char_len; i++) {
1427            *(comp_yomi + comp_len) = *pYomi;
1428            comp_len++;
1429            pYomi++;
1430        }
1431        *(comp_yomi + comp_len) = NJ_CHAR_NUL;
1432
1433        right = max - 1;
1434        left = 0;
1435        while (left <= right) {
1436            mid = left + ((right - left) / 2);
1437            p = ptr + (mid * NJ_INDEX_SIZE);
1438            que_id = GET_UINT16(p);
1439
1440
1441            ret = str_que_cmp(iwnn, handle, comp_yomi, comp_len, que_id, 1);
1442            if (ret < 0) {
1443                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI_MULTI, NJ_ERR_DIC_BROKEN);
1444            }
1445
1446#ifdef LEARN_DEBUG
1447            printf("   [%d][%d][%d]COMPARE:[%s] = %d\n", left, mid, right, str, ret);
1448#endif
1449            if (ret == 1) {
1450
1451                found = 1;
1452                break;
1453            } else if (ret == 0) {
1454
1455                right = mid - 1;
1456                if (mid == 0) {
1457                    break;
1458                }
1459            } else {
1460
1461                left = mid + 1;
1462            }
1463        }
1464
1465        if (found) {
1466            break;
1467        }
1468    }
1469
1470    if (!found) {
1471
1472        return 0;
1473    }
1474
1475
1476    if (mid == 0) {
1477        *from = mid;
1478    } else {
1479
1480        p = ((mid - 1) * NJ_INDEX_SIZE) + ptr;
1481
1482        for (cmp = mid - 1; cmp >= 0; cmp--) {
1483            que_id = GET_UINT16(p);
1484            ret = str_que_cmp(iwnn, handle, comp_yomi, comp_len, que_id, 1);
1485            if (ret < 0) {
1486                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI_MULTI, NJ_ERR_DIC_BROKEN);
1487            }
1488            if (ret == 2) {
1489                break;
1490            }
1491            p -= NJ_INDEX_SIZE;
1492        }
1493        if (cmp < 0) {
1494            *from = 0;
1495        } else {
1496            *from = (NJ_UINT16)cmp + 1;
1497        }
1498    }
1499
1500#ifdef LEARN_DEBUG
1501    printf("  >> from:(%d)\n", *from);
1502#endif
1503
1504
1505    if ((mid + 1) >= max) {
1506        *to = mid;
1507    } else {
1508
1509        p = ((mid + 1) * NJ_INDEX_SIZE) + ptr;
1510
1511        for (right = mid + 1; right < max; right++) {
1512            que_id = GET_UINT16(p);
1513            ret = str_que_cmp(iwnn, handle, yomi, len, que_id, 1);
1514            if (ret < 0) {
1515                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI_MULTI, NJ_ERR_DIC_BROKEN);
1516            }
1517            if (ret == 0) {
1518                break;
1519            }
1520            p += NJ_INDEX_SIZE;
1521        }
1522        *to = right - 1;
1523    }
1524
1525#ifdef LEARN_DEBUG
1526    printf("  >> to:(%d)\n", *to);
1527#endif
1528    return 1;
1529}
1530
1531static NJ_INT16 str_que_cmp(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_CHAR *yomi,
1532                            NJ_UINT16 yomiLen, NJ_UINT16 que_id, NJ_UINT8 mode) {
1533    NJ_UINT8  *queYomi;
1534    NJ_UINT8  *yomiPtr;
1535    NJ_UINT16 yomiByte;
1536    NJ_UINT16 yomiPos;
1537    NJ_UINT8  queYomiByte, queKouhoByte;
1538    NJ_UINT8  queYomiPos, queYomiSearchArea;
1539    NJ_INT16  complete;
1540    NJ_UINT8  *top_addr;
1541    NJ_UINT8  *bottom_addr;
1542    NJ_UINT16 que_size;
1543
1544
1545#ifdef IWNN_ERR_CHECK
1546    if (iwnn->err_check_flg == 6) {
1547        que_id = GET_LEARN_MAX_WORD_COUNT(handle);
1548    }
1549#endif
1550    if (que_id >= GET_LEARN_MAX_WORD_COUNT(handle)) {
1551
1552        return NJ_SET_ERR_VAL(NJ_FUNC_STR_QUE_CMP, NJ_ERR_DIC_BROKEN);
1553    }
1554
1555    queYomi = POS_TO_ADDRESS(handle, que_id);
1556#ifdef IWNN_ERR_CHECK
1557    if (iwnn->err_check_flg == 7) {
1558        *queYomi = 0x03;
1559    }
1560#endif
1561    switch (GET_TYPE_FROM_DATA(queYomi)) {
1562    case QUE_TYPE_EMPTY:
1563    case QUE_TYPE_JIRI:
1564    case QUE_TYPE_FZK:
1565        break;
1566    default:
1567
1568        return NJ_SET_ERR_VAL(NJ_FUNC_STR_QUE_CMP, NJ_ERR_DIC_BROKEN);
1569    }
1570
1571
1572    if ((mode == 2) && (yomiLen == 0)) {
1573        return 1;
1574    }
1575
1576
1577    queYomiByte = GET_YSIZE_FROM_DATA(queYomi);
1578    queKouhoByte= GET_KSIZE_FROM_DATA(queYomi);
1579
1580    top_addr = LEARN_DATA_TOP_ADDR(handle);
1581    que_size = QUE_SIZE(handle);
1582
1583
1584    queYomi += LEARN_QUE_STRING_OFFSET;
1585    queYomiSearchArea = (NJ_UINT8)(QUE_SIZE(handle) - LEARN_QUE_STRING_OFFSET);
1586
1587    complete = 0;
1588    yomiPos = 0; queYomiPos = 0;
1589    yomiPtr  = (NJ_UINT8*)yomi;
1590    yomiByte = yomiLen * sizeof(NJ_CHAR);
1591
1592
1593    while ((complete = (*yomiPtr - *queYomi)) == 0) {
1594        yomiPos++; queYomiPos++;
1595
1596        if (queYomiPos >= queYomiByte) {
1597            if (queYomiByte == yomiByte) {
1598
1599                return 1;
1600            } else if (mode == 2) {
1601
1602                return 2;
1603            } else {
1604
1605                return (mode + 1);
1606            }
1607        }
1608        if (yomiPos >= yomiByte) {
1609
1610            break;
1611        } else {
1612            yomiPtr++; queYomi++;
1613#ifdef IWNN_ERR_CHECK
1614            if (iwnn->err_check_flg == 8) {
1615                queYomiPos = queYomiSearchArea;
1616            }
1617#endif
1618            if (queYomiPos >= queYomiSearchArea) {
1619
1620                bottom_addr = top_addr;
1621                bottom_addr += que_size * GET_LEARN_MAX_WORD_COUNT(handle) - 1;
1622                if (queYomi >= bottom_addr) {
1623                    queYomi = top_addr;
1624                }
1625
1626
1627                if (*queYomi++ != QUE_TYPE_NEXT) {
1628
1629                    return NJ_SET_ERR_VAL(NJ_FUNC_STR_QUE_CMP, NJ_ERR_DIC_BROKEN);
1630                }
1631                queYomiSearchArea += (NJ_UINT8)(que_size - 1);
1632            }
1633        }
1634    }
1635    if (complete == 0) {
1636        if (yomiByte < queYomiByte) {
1637
1638            if (mode == 2) {
1639                return 1;
1640            }
1641
1642            return 0;
1643        } else {
1644
1645            return 2;
1646        }
1647    } else if (complete < 0) {
1648
1649        return 0;
1650    } else {
1651
1652        return 2;
1653    }
1654}
1655
1656static NJ_HINDO calculate_hindo(NJ_DIC_HANDLE handle, NJ_INT32 freq, NJ_DIC_FREQ *dic_freq, NJ_INT16 freq_max, NJ_INT16 freq_min) {
1657    NJ_UINT16 max;
1658    NJ_HINDO  hindo;
1659
1660
1661    max = GET_LEARN_MAX_WORD_COUNT(handle);
1662
1663
1664
1665
1666    if (NJ_GET_DIC_TYPE(handle) == NJ_DIC_TYPE_USER) {
1667
1668        hindo = (NJ_INT16)dic_freq->base;
1669    } else {
1670
1671        if (max > 1) {
1672
1673            hindo = CALCULATE_HINDO(freq, dic_freq->base, dic_freq->high, (max-1));
1674        } else {
1675
1676            hindo = (NJ_INT16)dic_freq->high;
1677        }
1678    }
1679    return NORMALIZE_HINDO(hindo, freq_max, freq_min);
1680}
1681
1682static NJ_HINDO get_hindo(NJ_CLASS *iwnn, NJ_SEARCH_LOCATION_SET *loctset,
1683                          NJ_UINT8 search_pattern) {
1684    NJ_WQUE   *que;
1685    NJ_UINT16 que_id, oldest;
1686    NJ_UINT8  offset;
1687    NJ_INT32  dic_freq;
1688    NJ_UINT16 max;
1689    NJ_UINT8  *learn_index_top_addr;
1690
1691
1692
1693    learn_index_top_addr = get_search_index_address(loctset->loct.handle, search_pattern);
1694
1695    que_id = (NJ_UINT16)GET_UINT16(learn_index_top_addr +
1696                                   ((loctset->loct.current & 0xffffU) * NJ_INDEX_SIZE));
1697    oldest = GET_LEARN_NEXT_WORD_POS(loctset->loct.handle);
1698
1699    offset = (loctset->loct.current_info & 0x0f);
1700    while (offset--) {
1701        que_id = search_next_que(loctset->loct.handle, que_id);
1702    }
1703
1704    que = get_que(iwnn, loctset->loct.handle, que_id);
1705    if (que == NULL) {
1706        return INIT_HINDO;
1707    }
1708
1709    max = GET_LEARN_MAX_WORD_COUNT(loctset->loct.handle);
1710    if (que_id >= oldest) {
1711        dic_freq = que_id - oldest;
1712    } else {
1713        dic_freq = que_id - oldest + max;
1714    }
1715
1716
1717    return calculate_hindo(loctset->loct.handle, dic_freq, &(loctset->dic_freq), 1000, 0);
1718}
1719
1720NJ_INT16 njd_l_get_word(NJ_CLASS *iwnn, NJ_SEARCH_LOCATION_SET *loctset, NJ_WORD *word) {
1721    NJ_WQUE *que;
1722    NJ_UINT16 que_id;
1723    NJ_UINT8 offset;
1724    NJ_UINT8 *learn_index_top_addr;
1725
1726
1727
1728    learn_index_top_addr = get_search_index_address(loctset->loct.handle, GET_LOCATION_OPERATION(loctset->loct.status));
1729
1730    que_id = (NJ_UINT16)GET_UINT16(learn_index_top_addr +
1731                                   ((loctset->loct.current & 0xffff) * NJ_INDEX_SIZE));
1732
1733    offset = (loctset->loct.current_info & 0x0f);
1734    while (offset--) {
1735        que_id = search_next_que(loctset->loct.handle, que_id);
1736    }
1737
1738    que = get_que(iwnn, loctset->loct.handle, que_id);
1739    if (que == NULL) {
1740        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_GET_WORD, NJ_ERR_CANNOT_GET_QUE);
1741    }
1742
1743    word->stem.loc = loctset->loct;
1744
1745    word->stem.loc.current &= 0x0000ffff;
1746    word->stem.loc.current |= ((NJ_UINT32)que_id << 16);
1747
1748
1749    word->stem.hindo = loctset->cache_freq;
1750
1751    NJ_SET_FPOS_TO_STEM(word, que->mae_hinsi);
1752    NJ_SET_YLEN_TO_STEM(word, que->yomi_len);
1753    if (que->hyouki_len > 0) {
1754        NJ_SET_KLEN_TO_STEM(word, que->hyouki_len);
1755    } else {
1756
1757        NJ_SET_KLEN_TO_STEM(word, que->yomi_len);
1758    }
1759    NJ_SET_BPOS_TO_STEM(word, que->ato_hinsi);
1760
1761
1762    word->stem.type = 0;
1763
1764    return 1;
1765}
1766
1767NJ_INT16 njd_l_get_stroke(NJ_CLASS *iwnn, NJ_WORD *word, NJ_CHAR *stroke, NJ_UINT16 size) {
1768    NJ_UINT16 que_id;
1769    NJ_CHAR   *str;
1770    NJ_UINT8  slen;
1771    NJ_UINT8  ylen;
1772
1773
1774    que_id = (NJ_UINT16)(word->stem.loc.current >> 16);
1775
1776
1777    ylen = (NJ_UINT8)NJ_GET_YLEN_FROM_STEM(word);
1778
1779    if ((NJ_UINT16)((ylen+ NJ_TERM_LEN)*sizeof(NJ_CHAR)) > size) {
1780
1781        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_GET_STROKE, NJ_ERR_BUFFER_NOT_ENOUGH);
1782    }
1783    if (ylen == 0) {
1784        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_GET_STROKE, NJ_ERR_INVALID_RESULT);
1785    }
1786    str = get_string(iwnn, word->stem.loc.handle, que_id, &slen);
1787
1788#ifdef IWNN_ERR_CHECK
1789    if (iwnn->err_check_flg == 9) {
1790        str = NULL;
1791    }
1792#endif
1793
1794    if (str == NULL) {
1795        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_GET_STROKE, NJ_ERR_DIC_BROKEN);
1796    }
1797
1798
1799    nj_strcpy(stroke, str);
1800
1801    return slen;
1802}
1803
1804NJ_INT16 njd_l_get_candidate(NJ_CLASS *iwnn, NJ_WORD *word,
1805                             NJ_CHAR *candidate, NJ_UINT16 size) {
1806    NJ_UINT16 que_id;
1807    NJ_CHAR   *str;
1808    NJ_UINT16 klen;
1809    NJ_UINT8  slen;
1810
1811
1812    que_id = (NJ_UINT16)(word->stem.loc.current >> 16);
1813
1814
1815    klen = NJ_GET_KLEN_FROM_STEM(word);
1816
1817    if (size < ((klen+NJ_TERM_LEN)*sizeof(NJ_CHAR))) {
1818
1819        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_GET_CANDIDATE, NJ_ERR_BUFFER_NOT_ENOUGH);
1820    }
1821    str = get_hyouki(iwnn, word->stem.loc.handle, que_id, &slen);
1822#ifdef IWNN_ERR_CHECK
1823    if (iwnn->err_check_flg == 10) {
1824        str = NULL;
1825    }
1826#endif
1827    if (str == NULL) {
1828
1829        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_GET_CANDIDATE, NJ_ERR_DIC_BROKEN);
1830    }
1831
1832
1833    nj_strcpy(candidate, str);
1834
1835    return klen;
1836}
1837
1838NJ_INT16 njd_l_check_dic(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle) {
1839    NJ_UINT16 flg;
1840    NJ_UINT16 word_cnt, max;
1841    NJ_UINT8 *ptr;
1842    NJ_UINT16 target_id;
1843    NJ_UINT16 i;
1844    NJ_UINT16 id1 = 0;
1845    NJ_UINT8 slen;
1846
1847
1848
1849    if ((NJ_GET_DIC_TYPE(handle) != NJ_DIC_TYPE_USER)) {
1850
1851        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC, NJ_ERR_DIC_TYPE_INVALID);
1852    }
1853
1854
1855    word_cnt = GET_LEARN_WORD_COUNT(handle);
1856    max = GET_LEARN_MAX_WORD_COUNT(handle);
1857    if (word_cnt > max) {
1858
1859        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC,
1860                              NJ_ERR_DIC_BROKEN);
1861    }
1862
1863    ptr = LEARN_INDEX_TOP_ADDR(handle);
1864    for (i = 0; i < word_cnt; i++) {
1865        id1 = GET_UINT16(ptr);
1866
1867        if (id1 >= max) {
1868            return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC,
1869                                  NJ_ERR_DIC_BROKEN);
1870        }
1871        ptr += NJ_INDEX_SIZE;
1872    }
1873
1874
1875    ptr = LEARN_INDEX_TOP_ADDR2(handle);
1876    for (i = 0; i < word_cnt; i++) {
1877        id1 = GET_UINT16(ptr);
1878
1879        if (id1 >= max) {
1880            return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC,
1881                                  NJ_ERR_DIC_BROKEN);
1882        }
1883        ptr += NJ_INDEX_SIZE;
1884    }
1885
1886
1887    flg = GET_UINT16(handle + POS_WRITE_FLG);
1888
1889    target_id = GET_UINT16(handle + POS_WRITE_FLG + 2);
1890
1891
1892
1893    if (((flg != word_cnt) && (flg != (word_cnt + 1)) && (flg != (word_cnt - 1))) ||
1894        (target_id >= max)) {
1895        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC,
1896                              NJ_ERR_DIC_BROKEN);
1897    }
1898
1899
1900    if (flg == (word_cnt + 1)) {
1901        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC, NJ_ERR_DIC_BROKEN);
1902    } else if (flg == (word_cnt - 1)) {
1903        return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC, NJ_ERR_DIC_BROKEN);
1904    }
1905
1906    word_cnt = GET_LEARN_WORD_COUNT(handle);
1907
1908    ptr = LEARN_INDEX_TOP_ADDR(handle);
1909    for (i = 0; i < word_cnt; i++) {
1910        id1 = GET_UINT16(ptr);
1911        if (get_hyouki(iwnn, handle, id1, &slen) == NULL) {
1912            return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC,
1913                                  NJ_ERR_DIC_BROKEN);
1914        }
1915        ptr += NJ_INDEX_SIZE;
1916    }
1917
1918    ptr = LEARN_INDEX_TOP_ADDR2(handle);
1919    for (i = 0; i < word_cnt; i++) {
1920        id1 = GET_UINT16(ptr);
1921
1922        if (id1 >= max) {
1923            return NJ_SET_ERR_VAL(NJ_FUNC_NJD_L_CHECK_DIC,
1924                                  NJ_ERR_DIC_BROKEN);
1925        }
1926        ptr += NJ_INDEX_SIZE;
1927    }
1928
1929    return 0;
1930}
1931
1932static NJ_INT16 get_cand_by_evaluate2(NJ_CLASS *iwnn, NJ_SEARCH_CONDITION *cond,
1933                                      NJ_SEARCH_LOCATION_SET *loctset,
1934                                      NJ_UINT8 search_pattern,
1935                                      NJ_UINT16 idx) {
1936    NJ_UINT16 from, to, i;
1937    NJ_UINT16 que_id, oldest;
1938    NJ_UINT32 max_value, eval, current;
1939    NJ_UINT8  *ptr, *p;
1940    NJ_WQUE *que;
1941    NJ_INT16 ret = 0;
1942    NJ_INT32 found = 0;
1943    NJ_UINT8 forward_flag = 0;
1944
1945
1946    NJ_UINT16               abIdx;
1947    NJ_UINT16               abIdx_old;
1948    NJ_UINT16               tmp_len;
1949    NJ_UINT16               yomi_clen;
1950    NJ_UINT16               j,l,m;
1951    NJ_UINT8                cmpflg;
1952    NJ_UINT8                endflg = 0;
1953    NJ_CHAR                 *str;
1954    NJ_CHAR                 *key;
1955    NJ_CHAR                 char_tmp[NJ_MAX_LEN + NJ_TERM_LEN];
1956    NJ_CHAR                 *pchar_tmp;
1957    NJ_SEARCH_CACHE         *psrhCache = cond->ds->dic[idx].srhCache;
1958    NJ_UINT16               endIdx;
1959    NJ_UINT8                slen;
1960    NJ_UINT16               addcnt = 0;
1961    NJ_CHAR                 *yomi;
1962    NJ_UINT8                aimai_flg = 0x01;
1963    NJ_CHARSET              *pCharset = cond->charset;
1964
1965
1966    if (NJ_GET_CACHEOVER_FROM_SCACHE(psrhCache)) {
1967        aimai_flg = 0x00;
1968    }
1969
1970
1971    ptr = get_search_index_address(loctset->loct.handle, cond->operation);
1972
1973
1974    oldest = GET_LEARN_NEXT_WORD_POS(loctset->loct.handle);
1975    max_value = oldest;
1976
1977
1978    current = 0;
1979    if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_NO_INIT) {
1980
1981
1982        key       = cond->ds->keyword;
1983        yomi      = cond->yomi;
1984        yomi_clen = cond->yclen;
1985
1986
1987        endflg = 0x00;
1988
1989        if (psrhCache->keyPtr[0] == 0xFFFF) {
1990            cmpflg = 0x01;
1991            psrhCache->keyPtr[0] = 0x0000;
1992        } else {
1993            cmpflg = 0x00;
1994        }
1995
1996        for (i = 0; i < yomi_clen; i++) {
1997            j = i;
1998
1999
2000            if (!cmpflg) {
2001
2002                if (((j != 0) && (psrhCache->keyPtr[j] == 0)) || (psrhCache->keyPtr[j+1] == 0)) {
2003
2004                    cmpflg = 0x01;
2005                } else {
2006
2007                }
2008            }
2009
2010            if (cmpflg) {
2011
2012                if (!j) {
2013
2014                    abIdx = 0;
2015                    addcnt = 0;
2016                    nj_charncpy(char_tmp, yomi, 1);
2017                    tmp_len = nj_strlen(char_tmp);
2018                    ret = search_range_by_yomi(iwnn, loctset->loct.handle, search_pattern,
2019                                               char_tmp, tmp_len, &from,
2020                                               &to, &forward_flag);
2021                    if (ret < 0) {
2022
2023
2024                        psrhCache->keyPtr[j+1] = abIdx;
2025                        loctset->loct.status = NJ_ST_SEARCH_END;
2026                        return ret;
2027                    } else if (ret > 0) {
2028
2029                        psrhCache->storebuff[abIdx].top    = from;
2030                        psrhCache->storebuff[abIdx].bottom = to;
2031                        psrhCache->storebuff[abIdx].idx_no = (NJ_INT8)tmp_len;
2032                        addcnt++;
2033                        abIdx++;
2034                        psrhCache->keyPtr[j+1] = abIdx;
2035                    } else {
2036                        psrhCache->keyPtr[j+1] = abIdx;
2037                    }
2038
2039                    if ((!endflg) && (pCharset != NULL) && aimai_flg) {
2040
2041                        for (l = 0; l < pCharset->charset_count; l++) {
2042
2043                            if (nj_charncmp(yomi, pCharset->from[l], 1) == 0) {
2044
2045                                nj_strcpy(char_tmp, pCharset->to[l]);
2046                                tmp_len = nj_strlen(char_tmp);
2047                                ret = search_range_by_yomi(iwnn, loctset->loct.handle, search_pattern,
2048                                                           char_tmp, tmp_len, &from, &to, &forward_flag);
2049                                if (ret < 0) {
2050
2051
2052                                    psrhCache->keyPtr[j+1] = abIdx;
2053                                    loctset->loct.status = NJ_ST_SEARCH_END;
2054                                    return ret;
2055                                } else if (ret > 0) {
2056
2057
2058                                    if (abIdx >= NJ_SEARCH_CACHE_SIZE) {
2059                                        psrhCache->keyPtr[j+1] = 0;
2060                                        return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_CACHE_NOT_ENOUGH);
2061                                    }
2062                                    psrhCache->storebuff[abIdx].top    = from;
2063                                    psrhCache->storebuff[abIdx].bottom = to;
2064                                    psrhCache->storebuff[abIdx].idx_no = (NJ_INT8)tmp_len;
2065                                    if (addcnt == 0) {
2066                                        psrhCache->keyPtr[j] = abIdx;
2067                                    }
2068                                    abIdx++;
2069                                    addcnt++;
2070                                    psrhCache->keyPtr[j+1] = abIdx;
2071                                } else {
2072                                    psrhCache->keyPtr[j+1] = abIdx;
2073                                }
2074                            }
2075                        }
2076                    }
2077                } else {
2078
2079                    if (psrhCache->keyPtr[j] == psrhCache->keyPtr[j-1]) {
2080
2081                        psrhCache->keyPtr[j+1] = psrhCache->keyPtr[j-1];
2082                        endflg = 0x01;
2083                    } else {
2084
2085                        endIdx = psrhCache->keyPtr[j];
2086                        abIdx_old = psrhCache->keyPtr[j-1];
2087
2088                        if (NJ_GET_CACHEOVER_FROM_SCACHE(psrhCache)) {
2089                            abIdx = psrhCache->keyPtr[j - 1];
2090                            psrhCache->keyPtr[j] = abIdx;
2091                        } else {
2092                            abIdx = psrhCache->keyPtr[j];
2093                        }
2094                        addcnt = 0;
2095
2096                        if ((abIdx > NJ_SEARCH_CACHE_SIZE) || (abIdx_old >= NJ_SEARCH_CACHE_SIZE) ||
2097                            (endIdx > NJ_SEARCH_CACHE_SIZE)) {
2098
2099                            return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_CACHE_BROKEN);
2100                        }
2101                        for (m = abIdx_old; m < endIdx; m++) {
2102
2103                            p = ptr + (psrhCache->storebuff[m].top * NJ_INDEX_SIZE);
2104                            que_id = GET_UINT16(p);
2105
2106
2107                            str = get_string(iwnn, loctset->loct.handle, que_id, &slen);
2108
2109                            if (str == NULL) {
2110                                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_DIC_BROKEN);
2111                            }
2112
2113
2114                            nj_strncpy(char_tmp, str, psrhCache->storebuff[m].idx_no);
2115                            char_tmp[psrhCache->storebuff[m].idx_no] = NJ_CHAR_NUL;
2116
2117                            pchar_tmp = &char_tmp[psrhCache->storebuff[m].idx_no];
2118                            nj_charncpy(pchar_tmp, yomi, 1);
2119                            tmp_len = nj_strlen(char_tmp);
2120
2121
2122                            ret = search_range_by_yomi2(iwnn, loctset->loct.handle, search_pattern,
2123                                                        char_tmp, tmp_len,
2124                                                        (NJ_UINT16)(psrhCache->storebuff[m].top),
2125                                                        (NJ_UINT16)(psrhCache->storebuff[m].bottom),
2126                                                        &from, &to, &forward_flag);
2127                            if (ret < 0) {
2128
2129
2130                                psrhCache->keyPtr[j+1] = abIdx;
2131                                loctset->loct.status = NJ_ST_SEARCH_END;
2132                                return ret;
2133                            } else if (ret > 0) {
2134
2135
2136                                if (abIdx >= NJ_SEARCH_CACHE_SIZE) {
2137                                    psrhCache->keyPtr[j+1] = 0;
2138                                    return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_CACHE_NOT_ENOUGH);
2139                                }
2140                                psrhCache->storebuff[abIdx].top    = from;
2141                                psrhCache->storebuff[abIdx].bottom = to;
2142                                psrhCache->storebuff[abIdx].idx_no = (NJ_INT8)tmp_len;
2143                                if (addcnt == 0) {
2144                                    psrhCache->keyPtr[j] = abIdx;
2145                                }
2146                                abIdx++;
2147                                addcnt++;
2148                                psrhCache->keyPtr[j+1] = abIdx;
2149                            } else {
2150                                psrhCache->keyPtr[j+1] = abIdx;
2151                            }
2152
2153                            if ((!endflg) && (pCharset != NULL) && aimai_flg) {
2154
2155                                for (l = 0; l < pCharset->charset_count; l++) {
2156
2157                                    if (nj_charncmp(yomi, pCharset->from[l], 1) == 0) {
2158
2159                                        tmp_len = nj_strlen(pCharset->to[l]);
2160
2161                                        nj_strncpy(pchar_tmp, pCharset->to[l], tmp_len);
2162                                        *(pchar_tmp + tmp_len) = NJ_CHAR_NUL;
2163                                        tmp_len = nj_strlen(char_tmp);
2164                                        ret = search_range_by_yomi2(iwnn, loctset->loct.handle, search_pattern,
2165                                                                    char_tmp, tmp_len,
2166                                                                    (NJ_UINT16)(psrhCache->storebuff[m].top),
2167                                                                    (NJ_UINT16)(psrhCache->storebuff[m].bottom),
2168                                                                    &from, &to, &forward_flag);
2169                                        if (ret < 0) {
2170
2171
2172                                            psrhCache->keyPtr[j+1] = abIdx;
2173                                            loctset->loct.status = NJ_ST_SEARCH_END;
2174                                            return ret;
2175                                        } else if (ret > 0) {
2176
2177
2178                                            if (abIdx >= NJ_SEARCH_CACHE_SIZE) {
2179                                                psrhCache->keyPtr[j+1] = 0;
2180                                                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_CACHE_NOT_ENOUGH);
2181                                            }
2182                                            psrhCache->storebuff[abIdx].top    = from;
2183                                            psrhCache->storebuff[abIdx].bottom = to;
2184                                            psrhCache->storebuff[abIdx].idx_no = (NJ_INT8)tmp_len;
2185                                            abIdx++;
2186                                            addcnt++;
2187                                            psrhCache->keyPtr[j+1] = abIdx;
2188                                        } else {
2189                                            psrhCache->keyPtr[j+1] = abIdx;
2190                                        }
2191                                    }
2192                                }
2193                            }
2194                        }
2195                    }
2196                }
2197            }
2198            yomi += UTL_CHAR(yomi);
2199            key  += UTL_CHAR(key);
2200        }
2201
2202
2203        if ((addcnt == 0) && (psrhCache->keyPtr[yomi_clen - 1] == psrhCache->keyPtr[yomi_clen])) {
2204            endflg = 0x01;
2205        }
2206
2207        if (endflg) {
2208            loctset->loct.status = NJ_ST_SEARCH_END;
2209            return 0;
2210        }
2211    } else if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_READY) {
2212        current = GET_UINT16(ptr + (loctset->loct.current * NJ_INDEX_SIZE));
2213        if (current < oldest) {
2214            current += GET_LEARN_MAX_WORD_COUNT(loctset->loct.handle);
2215        }
2216    } else {
2217        loctset->loct.status = NJ_ST_SEARCH_END;
2218        return 0;
2219    }
2220
2221
2222    j = cond->yclen - 1;
2223
2224    abIdx = psrhCache->keyPtr[j];
2225    abIdx_old = psrhCache->keyPtr[j+1];
2226
2227    endIdx = abIdx_old;
2228    if ((abIdx >= NJ_SEARCH_CACHE_SIZE) || (abIdx_old > NJ_SEARCH_CACHE_SIZE)) {
2229
2230        return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_CACHE_BROKEN);
2231    }
2232    p = ptr + (psrhCache->storebuff[abIdx].top * NJ_INDEX_SIZE);
2233    que_id = GET_UINT16(p);
2234    eval = current;
2235
2236
2237
2238    if (psrhCache->keyPtr[j] < psrhCache->keyPtr[j + 1]) {
2239        if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_NO_INIT) {
2240            endIdx = abIdx + 1;
2241            NJ_SET_AIMAI_TO_SCACHE(psrhCache);
2242        }
2243
2244        for (m = abIdx; m < endIdx; m++) {
2245            p = ptr + (psrhCache->storebuff[m].top * NJ_INDEX_SIZE);
2246            que_id = GET_UINT16(p);
2247            eval = current;
2248
2249            for (i = (NJ_UINT16)psrhCache->storebuff[m].top; i <= (NJ_UINT16)psrhCache->storebuff[m].bottom; i++) {
2250                que_id = GET_UINT16(p);
2251                if (que_id < oldest) {
2252                    eval = que_id + GET_LEARN_MAX_WORD_COUNT(loctset->loct.handle);
2253                } else {
2254                    eval = que_id;
2255                }
2256#ifdef LEARN_DEBUG
2257                printf("que(%d) : eval = %d : %d\n", que_id, eval, i);
2258#endif
2259                if (eval >= max_value) {
2260                    if ((GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_NO_INIT)
2261                        || ((GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_READY)
2262                            && (NJ_GET_AIMAI_FROM_SCACHE(psrhCache)))
2263                        || (eval < current)) {
2264
2265
2266
2267                        str = get_string(iwnn, loctset->loct.handle, que_id, &slen);
2268                        if (str == NULL) {
2269                            return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_DIC_BROKEN);
2270                        }
2271
2272
2273
2274                        que = get_que_allHinsi(iwnn, loctset->loct.handle, que_id);
2275                        if (njd_connect_test(cond, que->mae_hinsi, que->ato_hinsi)) {
2276
2277                            loctset->loct.current_info = (NJ_UINT8)0x10;
2278                            loctset->loct.current = i;
2279                            max_value = eval;
2280                            found = 1;
2281#ifdef LEARN_DEBUG
2282                            printf("---keep.");
2283#endif
2284                        }
2285                    }
2286                }
2287                p += NJ_INDEX_SIZE;
2288            }
2289        }
2290    }
2291
2292    if (GET_LOCATION_STATUS(loctset->loct.status) != NJ_ST_SEARCH_NO_INIT) {
2293        NJ_UNSET_AIMAI_TO_SCACHE(psrhCache);
2294    }
2295
2296
2297    if (found == 0) {
2298        loctset->loct.status = NJ_ST_SEARCH_END;
2299        return 0;
2300    } else {
2301        loctset->loct.status = NJ_ST_SEARCH_READY;
2302        loctset->cache_freq = get_hindo(iwnn, loctset, search_pattern);
2303        return 1;
2304    }
2305}
2306
2307static NJ_INT16 search_range_by_yomi2(NJ_CLASS *iwnn, NJ_DIC_HANDLE handle, NJ_UINT8 op,
2308                                      NJ_CHAR  *yomi, NJ_UINT16 len,
2309                                      NJ_UINT16 sfrom, NJ_UINT16 sto,
2310                                      NJ_UINT16 *from, NJ_UINT16 *to,
2311                                      NJ_UINT8 *forward_flag) {
2312    NJ_UINT16 right, mid = 0, left, max;
2313    NJ_UINT16 que_id;
2314    NJ_UINT8  *ptr, *p;
2315    NJ_CHAR  *str;
2316    NJ_INT16 ret = 0;
2317    NJ_INT32 found = 0;
2318    NJ_UINT8 slen;
2319    NJ_INT32 cmp;
2320
2321
2322
2323    ptr = get_search_index_address(handle, op);
2324
2325    max = GET_LEARN_WORD_COUNT(handle);
2326
2327    right = sto;
2328    left = sfrom;
2329
2330#ifdef LEARN_DEBUG
2331    printf("src:[%s]\n", yomi);
2332#endif
2333
2334    *forward_flag = 0;
2335
2336    while (left <= right) {
2337        mid = left + ((right - left) / 2);
2338        p = ptr + (mid * NJ_INDEX_SIZE);
2339        que_id = GET_UINT16(p);
2340        str = get_string(iwnn, handle, que_id, &slen);
2341        if (str == NULL) {
2342            return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_DIC_BROKEN);
2343        }
2344
2345
2346        ret = nj_strncmp(yomi, str, len);
2347
2348#ifdef LEARN_DEBUG
2349        printf("   [%d][%d][%d]COMPARE:[%s] = %d\n", left, mid, right, str, ret);
2350#endif
2351        if (ret == 0) {
2352
2353            found = 1;
2354            break;
2355        } else if (ret < 0) {
2356
2357            right = mid - 1;
2358            if (mid == 0) {
2359                break;
2360            }
2361        } else {
2362
2363            left = mid + 1;
2364        }
2365    }
2366
2367    if (!found) {
2368        return 0;
2369    }
2370
2371    if (mid == 0) {
2372        *from = mid;
2373    } else {
2374
2375        p = ((mid - 1) * NJ_INDEX_SIZE) + ptr;
2376
2377        for (cmp = mid - 1; cmp >= 0; cmp--) {
2378            que_id = GET_UINT16(p);
2379            str = get_string(iwnn, handle, que_id, &slen);
2380            if (str == NULL) {
2381                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_DIC_BROKEN);
2382            }
2383
2384
2385            if (nj_strncmp(yomi, str, len) != 0) {
2386                break;
2387            }
2388            p -= NJ_INDEX_SIZE;
2389        }
2390        if (cmp < 0) {
2391            *from = 0;
2392        } else {
2393            *from = (NJ_UINT16)cmp + 1;
2394        }
2395    }
2396
2397#ifdef LEARN_DEBUG
2398    printf("  >> from:(%d)\n", *from);
2399#endif
2400
2401    if ((mid + 1) >= max) {
2402        *to = mid;
2403    } else {
2404
2405        p = ((mid + 1) * NJ_INDEX_SIZE) + ptr;
2406
2407        for (right = mid + 1; right < max; right++) {
2408            que_id = GET_UINT16(p);
2409            str = get_string(iwnn, handle, que_id, &slen);
2410            if (str == NULL) {
2411                return NJ_SET_ERR_VAL(NJ_FUNC_SEARCH_RANGE_BY_YOMI, NJ_ERR_DIC_BROKEN);
2412            }
2413
2414
2415            if (nj_strncmp(yomi, str, len) != 0) {
2416                break;
2417            }
2418            p += NJ_INDEX_SIZE;
2419        }
2420        *to = right - 1;
2421    }
2422
2423#ifdef LEARN_DEBUG
2424    printf("  >> to:(%d)\n", *to);
2425#endif
2426    return 1;
2427}
2428
2429