1 /* Copyright 1994 NEC Corporation, Tokyo, Japan.
2  *
3  * Permission to use, copy, modify, distribute and sell this software
4  * and its documentation for any purpose is hereby granted without
5  * fee, provided that the above copyright notice appear in all copies
6  * and that both that copyright notice and this permission notice
7  * appear in supporting documentation, and that the name of NEC
8  * Corporation not be used in advertising or publicity pertaining to
9  * distribution of the software without specific, written prior
10  * permission.  NEC Corporation makes no representations about the
11  * suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
16  * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19  * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  */
22 
23 #if !defined(lint) && !defined(__CODECENTER__)
24 static char rcs_id[] = "$Id: permdic.c,v 1.8 2003/09/17 08:50:52 aida_s Exp $";
25 #endif
26 
27 #include	"RKintern.h"
28 
29 
30 #ifdef SVR4
31 #include	<unistd.h>
32 #endif
33 
34 #ifdef __CYGWIN32__
35 #include <fcntl.h> /* for O_BINARY */
36 #endif
37 
38 #define dm_xdm	dm_extdata.ptr
39 #define df_fdes	df_extdata.var
40 
41 extern	unsigned	_RkCalcLVO();
42 extern	Wchar		uniqAlnum();
43 
44 #ifdef MMAP
45 /* If you compile with Visual C++, then please comment out the next 3 lines. */
46 #include <sys/types.h>  /* mmap */
47 #include <sys/mman.h>   /* mmap */
48 #include <fcntl.h>      /* mmap */
49 extern int fd_dic;      /* mmap */
50 #endif
51 
52 static int
openDF(df,dfnm,w,gramoff,gramsz)53 openDF(df, dfnm, w, gramoff, gramsz)
54      struct DF	*df;
55      char	*dfnm;
56      int        *w;
57      off_t	*gramoff;
58      size_t	*gramsz;
59 {
60   struct HD	hd;
61   struct ND	nd, *xnd;
62   struct DM	*dm, *dmh;
63   off_t		off;
64   unsigned char	ll[4];
65   int		count = 0, err;
66   int		fd;
67   int errres = -1;
68 
69   *w = 0;
70   if ((fd = open(dfnm, 0)) == -1)
71     return errres;
72 #ifdef __CYGWIN32__
73   setmode(fd, O_BINARY);
74 #endif
75 
76   for (off = 0, err = 0; !err && _RkReadHeader(fd, &hd, off) >= 0;) {
77 
78     if (hd.flag[HD_CODM] > 0) {
79       _RkClearHeader(&hd);
80       break;
81     }
82     nd.time = hd.data[HD_TIME].var;
83     /* XXX: sanity check taking advantage of this CRC */
84     if (hd.flag[HD_CRC]) {
85       nd.crc = hd.data[HD_CRC].var;
86       nd.crc_found = 1;
87     } else {
88       nd.crc_found = 0;
89     }
90     nd.rec = hd.data[HD_REC].var;
91     nd.can = hd.data[HD_CAN].var;
92     nd.doff = off + hd.data[HD_HSZ].var;
93     nd.sz = hd.data[HD_SIZ].var;
94     nd.drsz = hd.data[HD_PGOF].var - hd.data[HD_DROF].var;
95     nd.pgsz = _RkCalcUnlog2(hd.data[HD_L2P].var) + 1;
96     nd.ttlpg = hd.data[HD_PAG].var;
97     nd.fd = fd;
98     nd.buf = (unsigned char *)0;
99     nd.pgs = (struct NP *)0;
100     nd.version = HD_VERSION(&hd);
101     off += hd.data[HD_SIZ].var;
102     if (!strncmp(".swd",
103 		 (char *)(hd.data[HD_DMNM].ptr
104 			  + strlen((char *)hd.data[HD_DMNM].ptr) - 4),
105 		 4)) {
106       if (nd.version >= 0x300702L) {
107 	if (hd.flag[HD_GRAM] == -1) {
108 	  *gramoff = hd.data[HD_GRAM].var;
109 	  *gramsz = hd.data[HD_GRSZ].var;
110 	} else {
111 	  *gramoff = 0;
112 	  *gramsz = 0;
113 	}
114       } else {
115 	if (lseek(fd, off, 0) < 0 || read(fd, (char *)ll, 4) != 4) {
116 	  err++;
117 	  *gramoff = 0;
118 	  *gramsz = 0;
119 	} else {
120 	  *gramoff = off;
121 	  *gramsz = (size_t)-1;
122 	  off += bst4_to_l(ll) + 4;
123 	}
124       }
125     }
126     dmh = &df->df_members;
127     for (dm = dmh->dm_next; dm != dmh; dm = dm->dm_next) {
128       if (!strcmp((char *)dm->dm_dicname, (char *)hd.data[HD_DMNM].ptr)) {
129 	if (!dm->dm_xdm) {
130 	  if (!(xnd = (struct ND *)malloc(sizeof(struct ND))))
131 	    break;
132 	  dm->dm_xdm = (pointer)xnd;
133 	  *xnd = nd;
134 	  dm->dm_flags |= DM_EXIST;
135 	  dm->dm_offset = xnd->doff;
136 	  count++;
137 	  break;
138 	}
139       }
140     }
141     _RkClearHeader(&hd);
142   }
143   _RkClearHeader(&hd);
144   df->df_size = off;
145   if (!count) {
146     (void)close(fd);
147     return errres;
148   }
149   return (df->df_fdes = fd);
150 }
151 
152 int
_Rkpopen(dm,dfnm,mode,gram)153 _Rkpopen(dm, dfnm, mode, gram)
154      struct DM	*dm;
155      char	*dfnm;
156      int	mode;
157      struct RkKxGram *gram; /* ARGSUSED */
158 {
159   struct DF	*df;
160   struct DD	*dd;
161   struct ND	*xdm;
162   int 		writable, i, readsize;
163   int fd;
164   off_t		gramoff;
165   size_t	gramsz;
166 
167   if (!(df = dm->dm_file) || !(dd = df->df_direct))
168     return -1;
169   if (!df->df_rcount) {
170     if ((df->df_fdes = (long)openDF(df, dfnm, &writable, &gramoff, &gramsz)) < 0)
171       return -1;
172     if (writable)
173       df->df_flags |= DF_WRITABLE;
174     else
175       df->df_flags &= ~DF_WRITABLE;
176     df->df_flags |= DF_EXIST;
177     dd->dd_rcount++;
178   }
179   if (!(dm->dm_flags & DM_EXIST))
180     return -1;
181   df->df_rcount++;
182   xdm = (struct ND *)dm->dm_xdm;
183   fd = df->df_fdes;
184 
185   if (!(xdm->buf = (unsigned char *)malloc((size_t)xdm->drsz))) {
186     return(-1);
187   }
188   if (!(xdm->pgs
189           = (struct NP *)malloc((size_t)(sizeof(struct NP) * xdm->ttlpg)))) {
190     (void)free((char *)xdm->buf);
191     xdm->buf = (unsigned char *)0;
192     return(-1);
193   }
194   for (i = 0; i < (int)xdm->ttlpg; i++) {
195     xdm->pgs[i].lnksz = (unsigned) 0;
196     xdm->pgs[i].ndsz = (unsigned) 0;
197     xdm->pgs[i].lvo = (unsigned long) 0;
198     xdm->pgs[i].csn = (unsigned long) 0;
199     xdm->pgs[i].flags = (unsigned) 0;
200     xdm->pgs[i].count = 0;
201     xdm->pgs[i].buf = (unsigned char *) 0;
202   }
203 
204   (void)lseek(fd, xdm->doff, 0);
205   readsize = read(fd, (char *)xdm->buf, (unsigned int) xdm->drsz);
206   if (readsize != ((int) xdm->drsz)) {
207     (void)free((char *)xdm->pgs);
208     (void)free((char *)xdm->buf);
209     xdm->buf = (unsigned char *)0;
210     xdm->pgs = (struct NP *)0;
211     return(-1);
212   }
213   if (dm->dm_class == ND_SWD && gramsz) {
214     struct RkKxGram *gram;
215 
216     lseek(fd, gramoff, 0);
217     gram = RkReadGram(fd, gramsz);
218     if (gram) {
219       dm->dm_gram = (struct RkGram *)malloc(sizeof(struct RkGram));
220       if (dm->dm_gram) {
221 	dm->dm_gram->gramdic = gram;
222 	dm->dm_gram->P_BB  = RkGetGramNum(gram, "BB");
223 	dm->dm_gram->P_NN  = RkGetGramNum(gram, "NN");
224 	dm->dm_gram->P_T00 = RkGetGramNum(gram, "T00");
225 	dm->dm_gram->P_T30 = RkGetGramNum(gram, "T30");
226 	dm->dm_gram->P_T35 = RkGetGramNum(gram, "T35");
227 #ifdef LOGIC_HACK
228 	dm->dm_gram->P_KJ  = RkGetGramNum(gram, "KJ");
229 #endif
230 	dm->dm_gram->P_Ftte = RkGetGramNum(gram, "Ftte");
231 	dm->dm_gram->refcount = 1;
232 	goto next;
233       }
234       RkCloseGram(gram);
235     }
236   }
237 
238  next:
239   if ((mode & DM_WRITABLE) && (df->df_flags & DF_WRITABLE)) {
240     dm->dm_flags |= DM_WRITABLE;
241   }
242   return 0;
243 }
244 
245 int
_Rkpclose(dm,dfnm,gram)246 _Rkpclose(dm, dfnm, gram)
247      struct DM	*dm;
248      char		*dfnm;
249      struct RkKxGram *gram; /* ARGSUSED */
250 {
251   struct DF	*df = dm->dm_file;
252   struct ND	*xdm = (struct ND *)dm->dm_xdm;
253   int		i;
254 
255   _RkKillCache(dm);
256   if (dm->dm_gram) {
257     dm->dm_gram->refcount--;
258     if (dm->dm_gram->refcount == 0) {
259       (void)RkCloseGram(dm->dm_gram->gramdic);
260       free((char *)dm->dm_gram);
261     }
262   }
263   if (xdm) {
264     if (xdm->pgs) {
265       for (i = 0; i < (int)xdm->ttlpg; i++)
266 	if (xdm->pgs[i].flags & RK_PG_LOADED) {
267 #ifdef MMAP
268 	  if (((int) (xdm->pgs[i].buf)) != -1)
269 	    munmap((caddr_t)xdm->pgs[i].buf, xdm->pgsz);
270 #else
271 	  if (xdm->pgs[i].buf) {
272 	    (void)free((char *)xdm->pgs[i].buf);
273 	  }
274 #endif
275 	  xdm->pgs[i].flags &= ~RK_PG_LOADED;
276 	}
277       (void)free((char *)xdm->pgs);
278       xdm->pgs = (struct NP *)0;
279     }
280     if (xdm->buf) {
281       (void)free((char *) xdm->buf);
282       xdm->buf = (unsigned char *)0;
283     }
284   }
285 
286   if (--df->df_rcount == 0)  {
287     int	fd;
288     struct DM	*dmh, *ddm;
289 
290     fd = df->df_fdes;
291 
292     (void)close(fd);
293     dmh = &df->df_members;
294     for (ddm = dmh->dm_next; ddm != dmh; ddm = ddm->dm_next) {
295       xdm = (struct ND *)ddm->dm_xdm;
296       if (xdm) {
297 	(void)free((char *)xdm);
298 	ddm->dm_xdm = (pointer)0;
299       }
300     }
301   }
302   return 0;
303 }
304 
305 static
306 unsigned char *
assurep(dic,id)307 assurep(dic, id)
308      struct ND	*dic;
309      int	id;
310 {
311   off_t	off = dic->doff + dic->drsz + dic->pgsz * id;
312   unsigned	size = dic->pgsz;
313   unsigned char	*buf;
314   int i;
315   int fd;
316 
317   fd = dic->fd;
318   if (!dic->pgs)
319     return((unsigned char *)0);
320   if ((unsigned)id >= dic->ttlpg)
321     return((unsigned char *)0);
322   if (!isLoadedPage(dic->pgs + id)) {
323 
324 #ifdef MMAP
325     buf = (unsigned char *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_dic, 0);
326     if ((int)buf == -1)
327       return((unsigned char *)0);
328 #else
329     if (!(buf = (unsigned char *)malloc(size)))
330       return((unsigned char *)0);
331 #endif
332     (void)lseek(fd, off, 0);
333     if (read(fd, (char *)buf, size) != (int)size) {
334       free((char *)buf);
335       return((unsigned char *)0);
336     }
337 
338     dic->pgs[id].buf = buf;
339     dic->pgs[id].count = 0;
340     dic->pgs[id].flags |= RK_PG_LOADED;
341     dic->pgs[id].ndsz = bst2_to_s(buf + 2);
342     dic->pgs[id].lnksz = bst2_to_s(buf + 4);
343     dic->pgs[id].lvo = bst3_to_l(buf + 7);
344     dic->pgs[id].csn = bst3_to_l(buf + 10);
345     return(buf);
346   } else {
347     return(dic->pgs[id].buf);
348   }
349 }
350 
351 int
_RkEql(a,b,n)352 _RkEql(a, b, n)
353      Wchar		*a;
354      unsigned char	*b;
355      int		n;
356 {
357   Wchar	c, d;
358   for (; n-- > 0; b += 2) {
359     c = uniqAlnum(*a++);
360     d = (*b << 8) | *(b+1);
361     if (c != d)
362       return(0);
363   }
364   return(1);
365 }
366 
367 static
368 readThisCache(dm, xdm, pgno, val, key, cur, ylen, nread, mc, nc, cf)
369      struct DM		*dm;
370      struct ND		*xdm;
371      long		pgno;
372      unsigned long	val;
373      Wchar		*key;
374      int		cur;
375      int		ylen;
376      struct nread	*nread;
377      int		mc;
378      int		nc;
379      int		*cf;
380 {
381   int		remlen;
382   unsigned char	*wrec1, *wrec;
383 
384   if (xdm->pgs[pgno].buf) {
385     if (*(wrec1 = wrec = xdm->pgs[pgno].buf + val) & 0x80)
386       wrec1 += 2;
387     wrec1 += 2;
388     remlen = (*wrec >> 1) & 0x3f;
389     if (_RkEql(key + cur, (unsigned char *)wrec1, remlen)) {
390       if (remlen + cur > ylen)
391 	(*cf)++;
392       else if (nc < mc) {
393 	nread[nc].cache = _RkReadCache(dm, (long)wrec);
394 	if (nread[nc].cache) {
395 	  if (_RkGetLink(xdm, pgno, val, &nread[nc].offset, &nread[nc].csn) < 0) {
396 	    _RkDerefCache(nread[nc].cache);
397 	    return(0);
398 	  }
399 	  nread[nc].nk = cur + remlen;
400 	  nc++;
401 	} else
402 	  (*cf)++;
403       } else
404 	(*cf)++;
405     }
406   }
407   return(nc);
408 }
409 
410 static int
SearchInPage(dm,xdm,pgno,buf,val,key,cur,ylen,nread,mc,nc,cf)411 SearchInPage(dm, xdm, pgno, buf, val, key, cur, ylen, nread, mc, nc, cf)
412      struct DM		*dm;
413      struct ND		*xdm;
414      unsigned char	*buf;
415      long		pgno;
416      unsigned long	val;
417      Wchar		*key;
418      int		cur;
419      int		ylen;
420      struct nread	*nread;
421      int		mc;
422      int		nc;
423      int		*cf;
424 {
425   Wchar		kv, wc;
426   unsigned char	*pos = buf + val;
427 
428   if (!*pos && !*(pos + 1)) {
429     val = ((*(pos + 2) & 0x3f) << BIT_UNIT) | *(pos + 3);
430     nc = readThisCache(dm, xdm, pgno, val, key,
431 		       cur, ylen, nread, mc, nc, cf);
432     if (*(pos + 2) & LAST_NODE)
433       return(nc);
434     pos += 4;
435   }
436   if (cur == ylen) {
437     (*cf)++;
438     return(nc);
439   }
440   kv = uniqAlnum(*(key + cur));
441   for (wc = bst2_to_s(pos); wc != kv; pos += 4, wc = bst2_to_s(pos)) {
442     if (*(pos + 2) & LAST_NODE)
443       return(nc);
444   }
445   val = ((*(pos + 2) & 0x3f) << BIT_UNIT) | *(pos + 3);
446     cur++;
447   if (*(pos + 2) & WORD_NODE)
448     nc = readThisCache(dm, xdm, pgno, val, key,
449 		       cur, ylen, nread, mc, nc, cf);
450   else
451     nc = SearchInPage(dm, xdm, pgno, buf, val, key,
452 		      cur, ylen, nread, mc, nc, cf);
453   return(nc);
454 }
455 
456 static int
SearchInDir(dm,xdm,pos,key,cur,ylen,nread,mc,nc,cf)457 SearchInDir(dm, xdm, pos, key, cur, ylen, nread, mc, nc, cf)
458      struct DM		*dm;
459      struct ND		*xdm;
460      unsigned char	*pos;
461      Wchar		*key;
462      int		cur;
463      int		ylen;
464      struct nread	*nread;
465      int		mc;
466      int		nc;
467      int		*cf;
468 {
469   Wchar		kv, wc, nw;
470   unsigned long	val;
471   long		next, pgno, iw;
472   unsigned char	*p;
473 
474   nw = bst2_to_s(pos);
475   pos += 5;
476   if (!*pos && !*(pos + 1)) {
477     val = bst3_to_l(pos + 2);
478     if (val & ~VMASK) {
479       val &= VMASK;
480       pgno = (val - xdm->drsz) / xdm->pgsz;
481       val -= pgno * xdm->pgsz + xdm->drsz;
482       if (assurep(xdm, pgno))
483 	nc = readThisCache(dm, xdm, pgno, val, key,
484 			   cur, ylen, nread, mc, nc, cf);
485     }
486   }
487   if (cur == ylen) {
488     (*cf)++;
489     return(nc);
490   }
491   kv = uniqAlnum(*(key + cur));
492   next = (int)(kv % nw);
493   do {
494     p = pos + (((Wchar) next++) % nw) * 5;
495     if ((wc = bst2_to_s(p)) == 0xffff)
496       return(nc);
497   } while (wc != kv);
498   val = bst3_to_l(p + 2);
499   cur++;
500   iw = (val & ~VMASK);
501   val &= VMASK;
502   if (iw) {
503     pgno = (val - xdm->drsz) / xdm->pgsz;
504     val -= pgno * xdm->pgsz + xdm->drsz;
505     if (assurep(xdm, pgno))
506       nc = readThisCache(dm, xdm, pgno, val, key,
507 			 cur, ylen, nread, mc, nc, cf);
508   } else {
509     if (val < xdm->drsz)
510       nc = SearchInDir(dm, xdm, xdm->buf + val, key,
511 		       cur, ylen, nread, mc, nc, cf);
512     else {
513       pgno = (val - xdm->drsz) / xdm->pgsz;
514       val -= pgno * xdm->pgsz + xdm->drsz;
515       p = assurep(xdm, pgno);
516       if (p)
517 	nc = SearchInPage(dm, xdm, pgno, p, val, key,
518 			  cur, ylen, nread, mc, nc, cf);
519     }
520   }
521   return(nc);
522 }
523 
524 int
_Rkpsearch(cx,dm,key,n,nread,mc,cf)525 _Rkpsearch(cx, dm, key, n, nread, mc, cf)
526      struct RkContext	*cx;
527      struct DM		*dm;
528      Wchar		*key;
529      int		n;
530      struct nread	*nread;
531      int		mc;
532      int		*cf;
533 /* ARGSUSED */
534 {
535   struct ND	*xdm;
536 
537   *cf = 0;
538   xdm = (struct ND *)dm->dm_xdm;
539   if (xdm) {
540     if (xdm->buf)
541       return(SearchInDir(dm, xdm, xdm->buf, key, 0, n, nread, mc, 0, cf));
542   }
543   return(0);
544 }
545 
546 int
_Rkpio(dm,cp,io)547 _Rkpio(dm, cp, io)
548      struct DM		*dm;
549      struct ncache	*cp;
550      int		io;
551 /* ARGSUSED */
552 {
553   if (io == 0) {
554     cp->nc_word = (Wrec *)cp->nc_address;
555     cp->nc_flags |= NC_NHEAP;
556   }
557   return 0;
558 }
559 
560 #if 0 /* �Ȥ��Ƥ��ʤ��ΤǤȤꤢ���������Ȥˤ��� */
561 static void
562 ch_perm(qm, offset, size, num)
563      struct DM  *qm;
564      unsigned   offset;
565      int        size, num;
566 {
567   unsigned char	tmp[8192];
568   /* I leave this stack located array because of it is not used */
569 
570   if (num > 0) {
571     _RkCopyBits(tmp, 0, size, qm->dm_qbits, offset, num);
572     _RkCopyBits(qm->dm_qbits, offset + 0, size,
573 		qm->dm_qbits, offset + num*size, 1);
574     _RkCopyBits(qm->dm_qbits, offset + size, size, tmp, 0, num);
575   }
576 }
577 #endif
578 
579 #define PERM_WRECSIZE 2048
580 #define PERM_NREADSIZE 128
581 
582 int
_Rkpctl(dm,qm,what,arg,gram)583 _Rkpctl(dm, qm, what, arg, gram)
584      struct DM	*dm;
585      struct DM	*qm;
586      int	what;
587      Wchar	*arg;
588      struct RkKxGram *gram;
589 {
590   int		nc, cf = 0, ret = -1;
591   struct ND	*xdm;
592   unsigned long	lucks[2];
593 #ifndef USE_MALLOC_FOR_BIG_ARRAY
594   Wrec		wrec[PERM_WRECSIZE];
595   Wchar         key[64];
596   struct nread  nread[PERM_NREADSIZE];
597   unsigned	permutation[RK_CAND_NMAX];
598 #else
599   Wrec *wrec;
600   Wchar *key;
601   struct nread *nread;
602   unsigned *permutation;
603   wrec = (Wrec *)malloc(sizeof(Wrec) * PERM_WRECSIZE);
604   key = (Wchar *)malloc(sizeof(Wchar) * 64);
605   nread = (struct nread *)malloc(sizeof(struct nread) * PERM_NREADSIZE);
606   permutation = (unsigned *)malloc(sizeof(unsigned) * RK_CAND_NMAX);
607   if (!wrec || !key || !nread || !permutation) {
608     if (wrec) (void)free((char *)wrec);
609     if (key) (void)free((char *)key);
610     if (nread) (void)free((char *)nread);
611     if (permutation) (void)free((char *)permutation);
612     return ret;
613   }
614 #endif
615 
616   if (!dm  || !qm || (qm && !qm->dm_qbits)) {
617     goto done;
618   }
619 
620   if ((qm->dm_flags & (DM_WRITABLE | DM_WRITEOK)) ==
621       (DM_WRITABLE | DM_WRITEOK)) {
622     /* (writable and write ok) */
623 
624     if (RkParseOWrec(gram, arg, wrec, PERM_WRECSIZE, lucks)) {
625       Wrec	    *p, *q, *kanji;
626       Wchar         *wkey;
627       int	    maxcache = PERM_NREADSIZE;
628       int           ylen, klen, cnum, y_off = 2, k_off;
629 
630 
631       ylen = (wrec[0] >> 1) & 0x3f;
632       if (wrec[0] & 0x80)
633 	y_off += 2;
634       p = wrec + y_off;
635       q = p + (ylen * 2);
636       for (wkey = key; p < q ; wkey++) {
637 	*wkey = (*p << 8) | *(p + 1);
638 	p += 2;
639       }
640       *(key+ylen) = 0;
641 
642       /* �ʻ졢��������μ��Ф� */
643       k_off = y_off + ylen * 2;
644       klen = (wrec[k_off] >> 1) & 0x7f;
645       cnum = ((wrec[k_off] & 0x01) << 8) | wrec[k_off+1];
646       kanji = wrec + k_off + 2;
647 
648       nc = -1;
649       xdm = (struct ND *)dm->dm_xdm;
650       if (xdm) {
651 	if (xdm->buf)
652 	  nc = SearchInDir(dm, xdm, xdm->buf, key, 0, ylen, nread,
653 			   maxcache, 0, &cf);
654       }
655 
656       if (nc > 0) {
657 	struct nread	*thisRead;
658 	struct ncache	*thisCache;
659 	unsigned char	*wp;
660 	int             nk, nl, pre;
661 	unsigned long	offset;
662 	int		bitSize, fnum = -1, nnum, i;
663 
664 	for (i = 0 ; i < nc ; i++) {
665 	  if (nread[i].nk == ylen) {
666 	    break;
667 	  }
668 	}
669 	/* �Ȥ�ʤ�ñ�����Ϥ��餫���� _RkDerefCache ���� */
670 	for (pre = 0 ; pre < nc ; pre++) {
671 	  if (pre != i) {
672 	    thisRead = nread + pre;
673 	    thisCache = thisRead->cache;
674 	    _RkDerefCache(thisCache);
675 	  }
676 	}
677 
678 	if (i < nc) {
679 	  thisRead = nread + i;
680 	  thisCache = thisRead->cache;
681 	  wp = thisCache->nc_word;
682 
683 	  nk = _RkCandNumber(wp);
684 	  nl = (*wp >> 1) & 0x3f;
685 	  if (*wp & 0x80)
686 	    wp += 2;
687 	  wp += 2 + nl *2;
688 
689 	/* ��������ʬ�Ǽ���β����ܤˤǤƤ��뤫 (fnum) ��õ�� */
690 	  for (i = 0; i < nk; i++) {
691 	    unsigned char	*kp;
692 
693 	    nl = (*wp >> 1) & 0x7f;               /* ����Ĺ */
694 	    nnum = ((*wp & 0x01) << 8) | *(wp+1); /* �ʻ��ֹ� */
695 	    if (nl == klen && nnum == cnum) {
696 	      int lc;
697 
698 	      for (lc = 0, kp = wp + 2; lc < klen*2; lc++) {
699 		if (*(kanji+lc) != *(kp+lc))
700 		  break;
701 	      }
702 	      if (lc == klen*2) {
703 		fnum = i;
704 		break;
705 	      }
706 	    }
707 	    wp += 2 + nl*2;
708 	  }
709 
710 	  offset = thisRead->offset;
711 	  if (fnum >= 0 && fnum < nk && 0 < thisRead->nk &&
712 	      thisRead->nk <= ylen && thisRead->nk <= RK_KEY_WMAX)  {
713 	    int	   ecount, cval, i, dn = -1, ndel = 0;
714 
715 	    bitSize = _RkCalcLog2(nk + 1) + 1;
716 	    _RkUnpackBits(permutation, qm->dm_qbits, offset, bitSize, nk);
717 	    switch (what) {
718 	    case DST_DoDefine:
719 	      for (ecount = cval = i = 0; i < nk; i++) {
720 		if ((int)permutation[i]/2 > nk) {
721 		  ecount++;
722 		  break;
723 		};
724 		cval += permutation[i];
725 		if ((unsigned)nk == permutation[i]/2 && dn < 0)
726 		  dn = i;
727 		if ((unsigned)fnum == permutation[i]/2) {
728 		  ndel = -1;
729 		  dn = i;
730 		}
731 	      }
732 	      break;
733 	    case DST_DoDelete:
734 	      for (ecount = cval = i = 0; i < nk; i++) {
735 		if ((int)permutation[i]/2 >  nk) {
736 		  ecount++;
737 		  break;
738 		};
739 		cval += permutation[i];
740 		if ((unsigned)fnum == permutation[i]/2)
741 		  dn = i;
742 	      };
743 	      break;
744 	    }
745 	    if (ecount || cval < (nk-1)*(nk-2)) {
746 	      for (i = 0; i < nk; i++)
747 		permutation[i] = 2*i;
748 	      _RkPackBits(qm->dm_qbits, offset, bitSize, permutation, nk);
749 	    } else {
750 	      if (dn >= 0) {
751 		if (!ndel) {
752 		  switch (what) {
753 		  case DST_DoDefine:
754 		    _RkSetBitNum(qm->dm_qbits, offset, bitSize, dn, fnum*2);
755 /*		  �������¤ӽ���ѹ�����ؿ������Ȥꤢ���������Ȥˤ��롣
756                  ch_perm(qm, offset, bitSize, dn);
757 */
758 		    break;
759 		  case DST_DoDelete:
760 		    _RkSetBitNum(qm->dm_qbits, offset, bitSize, dn, nk*2);
761 		    break;
762 		  }
763 		  qm->dm_flags |= DM_UPDATED;
764 		}
765 		_RkDerefCache(thisCache);
766 		ret = 0;
767 		goto done;
768 	      }
769 	    }
770 	  }
771 	  _RkDerefCache(thisCache);
772 	}
773       }
774     }
775   }
776  done:
777 #ifdef USE_MALLOC_FOR_BIG_ARRAY
778   (void)free((char *)wrec);
779   (void)free((char *)key);
780   (void)free((char *)nread);
781   (void)free((char *)permutation);
782 #endif
783   return ret;
784 }
785 
786 int
_Rkpsync(cx,dm,qm)787 _Rkpsync(cx, dm, qm)
788      struct RkContext *cx;
789      struct DM	*dm, *qm;
790 {
791   struct DF	*df;
792   struct DD     *dd;
793 #ifdef MMAP
794   struct ND     *dic;
795 #endif
796   char	*file;
797 
798   if (qm) {
799     df = qm->dm_file;
800     dd = df->df_direct;
801     file = _RkCreatePath(dd, df->df_link);
802     if (file) {
803       int i;
804 #ifdef MMAP
805       int j;
806 #endif
807       i = FQsync(cx, dm, qm, file);
808       (void)free(file);
809 #ifdef MMAP
810       dic = (struct ND *)dm->dm_xdm;
811       if(dic)
812         for(j=0;j<dic->ttlpg;j++) {
813           if (isLoadedPage(dic->pgs + j))
814             if (_RkDoInvalidateCache(dic->pgs[j].buf, dic->pgsz) == 1) {
815 	      if (((int) (dic->pgs[j].buf)) != -1)
816 	        munmap((caddr_t)dic->pgs[j].buf, dic->pgsz);
817               dic->pgs[j].buf = (unsigned char *)0;
818               dic->pgs[j].lnksz = (unsigned) 0;
819               dic->pgs[j].ndsz = (unsigned) 0;
820               dic->pgs[j].lvo = (unsigned) 0;
821               dic->pgs[j].csn = (unsigned) 0;
822               dic->pgs[j].flags = (unsigned) 0;
823               dic->pgs[j].count = 0;
824             }
825         }
826 #endif
827       return (i);
828     }
829   }
830   return (0);
831 }
832 /* vim: set sw=2: */
833