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