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 rcsid[]="$Id: context.c,v 1.5 2003/09/17 08:50:52 aida_s Exp $";
25 #endif
26 /*LINTLIBRARY*/
27
28 #include "RKintern.h"
29 #include "patchlevel.h"
30 #include <canna/jrkanji.h>
31
32 #include <errno.h>
33
34 static unsigned long now_context = 0L;
35
36 #define Calloc calloc
37 #define cx_gwt cx_extdata.ptr
38 #define STRCMP(d, s) strcmp((char *)(d), (char *)(s))
39
40 struct RkGram SG;
41 struct RkParam SX;
42
43 /* RkInitialize: Renbunsetsu Henkan shokika
44 * subeteno Renbunsetsu henkan kannsuu wo siyou suru maeni
45 * itido dake call suru koto.
46 * returns: -1/0
47 */
48 static struct RkContext *CX;
49
50 #ifdef MMAP
51 /* If you compile with Visual C++, then please comment out the next 3 lines. */
52 #include <sys/types.h> /* mmap */
53 #include <sys/mman.h> /* mmap */
54 #include <fcntl.h> /* mmap */
55 int fd_dic = -1; /* mmap */
56 #endif
57
58 #ifdef WINDOWS_STYLE_FILENAME
59 #define DEFAULTGRAMDIC "/canna/fuzokugo.cbd"
60 #endif
61
62 #ifndef DEFAULTGRAMDIC
63 #define DEFAULTGRAMDIC "/canna/fuzokugo.d"
64 #endif
65
66 static int
_RkInitialize(ddhome,numCache)67 _RkInitialize(ddhome, numCache)
68 char *ddhome;
69 int numCache;
70 {
71 int i = strlen(ddhome);
72 struct RkParam *sx = &SX;
73 struct DD *dd = &sx->dd;
74 char *gramdic, *path;
75 int con;
76 #ifdef __EMX__
77 struct stat statbuf;
78 #endif
79
80 #ifdef MMAP
81 if((fd_dic == -1) && (fd_dic = open("/dev/zero", O_RDWR)) < 0) {
82 con = -1;
83 goto return_con;
84 }
85 #endif
86
87 if (sx->flag & SX_INITED) {
88 con = -1;
89 goto return_con;
90 }
91
92 gramdic = malloc(strlen(DEFAULTGRAMDIC) + i + 1);
93 if (gramdic) {
94 strcpy(gramdic, ddhome);
95 strcat(gramdic, DEFAULTGRAMDIC);
96 SG.gramdic = RkOpenGram(gramdic);
97 (void)free(gramdic);
98 if (SG.gramdic) {
99 /* confirm user/ and group/ directory */
100 path = malloc(strlen(ddhome) + strlen(USER_DIC_DIR) + 2);
101 if (path) {
102 strcpy(path, ddhome);
103 strcat(path, "/");
104 strcat(path, USER_DIC_DIR);
105 if (mkdir(path, MKDIR_MODE) < 0 &&
106 errno != EEXIST) {
107 free(path);
108 }
109 else {
110 free(path);
111
112 path = malloc(strlen(ddhome) + strlen(GROUP_DIC_DIR) + 2);
113 if (path) {
114 strcpy(path, ddhome);
115 strcat(path, "/");
116 strcat(path, GROUP_DIC_DIR);
117 if (mkdir(path, MKDIR_MODE) < 0 &&
118 errno != EEXIST) {
119 free(path);
120 }
121 else {
122 free(path);
123
124 sx->word = (struct nword *)0;
125 dd->dd_next = dd->dd_prev = dd;
126 sx->ddhome = allocStr(ddhome);
127 if (sx->ddhome) {
128 SG.P_BB = RkGetGramNum(SG.gramdic, "BB");
129 SG.P_NN = RkGetGramNum(SG.gramdic, "NN");
130 SG.P_T00 = RkGetGramNum(SG.gramdic, "T00");
131 SG.P_T30 = RkGetGramNum(SG.gramdic, "T30");
132 SG.P_T35 = RkGetGramNum(SG.gramdic, "T35");
133 #ifdef LOGIC_HACK
134 SG.P_KJ = RkGetGramNum(SG.gramdic, "KJ");
135 #endif
136 SG.P_Ftte = RkGetGramNum(SG.gramdic, "Ftte");
137 CX = (struct RkContext *)
138 Calloc(INIT_CONTEXT, sizeof(struct RkContext));
139 if (CX) {
140 now_context += INIT_CONTEXT;
141 if (_RkInitializeCache(numCache) == 0) {
142 sx->ddpath = _RkCreateDDP(SYSTEM_DDHOME_NAME);
143 if (sx->ddpath) {
144 con = RkwCreateContext();
145 if (con >= 0) {
146 sx->flag |= SX_INITED;
147 goto return_con;
148 }
149 _RkFreeDDP(sx->ddpath);
150 sx->ddpath = (struct DD **)0;
151 }
152 _RkFinalizeCache();
153 }
154 free((char *)CX);
155 now_context = 0L;
156 }
157 free(sx->ddhome);
158 }
159 }
160 }
161 }
162 }
163 RkCloseGram(SG.gramdic);
164 }
165 }
166 con = -1;
167 return_con:
168 return con;
169 }
170
171 int
RkwInitialize(ddhome)172 RkwInitialize(ddhome)
173 char *ddhome;
174 {
175 /*
176 * Word: ????
177 * Cache: 36B*512 = 20KB
178 * Heap: 30*1024B = 30KB
179 */
180 return(ddhome ? _RkInitialize(ddhome, 512*10) : -1);
181 }
182
183 /* RkFinalize: Renbunsetu henkan shuuryou shori
184 *
185 */
186 static void
_RkFinalizeWord()187 _RkFinalizeWord() /* finalize free word list */
188 {
189 struct nword *w, *t;
190
191 /* dispose each page in list */
192 for (w = SX.page; w; w = t) {
193 t = w->nw_next;
194 (void)free((char *)w);
195 }
196 SX.word = (struct nword *)0;
197 SX.page = (struct nword *)0;
198 SX.word_in_use = 0;
199 SX.page_in_use = 0;
200 }
201
202 void
RkwFinalize()203 RkwFinalize()
204 {
205 struct RkParam *sx = &SX;
206 int i;
207
208 /* already initialized */
209 if (!(sx->flag & SX_INITED))
210 return;
211 /* houchi sareta context wo close */
212 for(i = 0; (unsigned long)i < now_context; i++)
213 if (IS_LIVECTX(&CX[i]))
214 RkwCloseContext(i);
215 (void)free((char *)CX);
216 now_context = 0L;
217 /* sonohoka no shuuryou shori */
218 _RkFinalizeWord();
219 _RkFinalizeCache();
220 (void)free((char *)sx->ddhome);
221 sx->ddhome = (char *)0;
222 _RkFreeDDP(sx->ddpath);
223 RkCloseGram(SG.gramdic);
224 sx->flag &= ~SX_INITED;
225
226 #ifdef MMAP
227 close(fd_dic);
228 fd_dic = -1;
229 #endif
230
231 return;
232 }
233
234 /* RkGetSystem: System heno pointer wo motomeru
235 */
236 struct RkParam *
RkGetSystem()237 RkGetSystem()
238 {
239 return(&SX);
240 }
241
242 /* RkGetSystemDD: System heno pointer wo motomeru
243 */
244 struct DD *
RkGetSystemDD()245 RkGetSystemDD()
246 {
247 struct RkParam *sx;
248 return(((sx = RkGetSystem()) && sx->ddpath) ? sx->ddpath[0] : (struct DD *)0);
249 }
250
251 /* RkGetContext: Context heno pointer wo motomeru
252 * -> RKintern.h
253 */
254 struct RkContext *
RkGetContext(cx_num)255 RkGetContext(cx_num)
256 int cx_num;
257 {
258 return(IsLiveCxNum(cx_num) ? &CX[cx_num] : (struct RkContext *)0);
259 }
260
261 struct RkContext *
RkGetXContext(cx_num)262 RkGetXContext(cx_num)
263 int cx_num;
264 {
265 struct RkContext *cx;
266
267 cx = RkGetContext(cx_num);
268 if (cx)
269 if (!IS_XFERCTX(cx))
270 cx = (struct RkContext *)0;
271 return(cx);
272 }
273
274 void
_RkEndBun(cx)275 _RkEndBun(cx)
276 struct RkContext *cx;
277 {
278 struct DD **ddp = cx->ddpath;
279 int c;
280
281 cx->flags &= ~(CTX_XFER|CTX_XAUT);
282 cx->concmode &= ~(RK_CONNECT_WORD | RK_MAKE_WORD |
283 RK_MAKE_KANSUUJI | RK_MAKE_EISUUJI);
284 for (c = 0; c < 4; c++) {
285 struct MD *head, *md, *nd;
286
287 head = cx->md[c];
288 for (md = head->md_next; md != head; md = nd) {
289 struct DM *dm = md->md_dic;
290 struct DF *df = dm->dm_file;
291 struct DD *dd = df->df_direct;
292
293 nd = md->md_next;
294 if (md->md_flags & MD_MPEND) /* release pending */
295 md->md_flags &= ~MD_MPEND;
296 if (md->md_flags & MD_UPEND) /* unmount pending */
297 _RkUmountMD(cx, md);
298 else
299 if (!_RkIsInDDP(ddp, dd)) /* unreachable */
300 _RkUmountMD(cx, md);
301 };
302 };
303 }
304
305 /* RkSetDicPath
306 *
307 */
308
309 int
RkwSetDicPath(cx_num,path)310 RkwSetDicPath(cx_num, path)
311 int cx_num;
312 char *path;
313 {
314 struct RkContext *cx = RkGetContext(cx_num);
315 struct DD **new;
316
317 new = _RkCreateDDP(path);
318 if (new) {
319 _RkFreeDDP(cx->ddpath);
320 cx->ddpath = new;
321 return(0);
322 };
323 return(-1);
324 }
325
326 /*
327 fillContext -- ����ƥ����ȹ�¤�Τη�ޤä��Ȥ�����ͤ����Ƥ�롣
328
329 return value:
330 0 OK
331 -1 ����
332 */
333
334 static int
fillContext(cx_num)335 fillContext(cx_num)
336 int cx_num;
337 {
338 struct RkContext *cx = &CX[cx_num];
339 int i;
340
341 /* create mount list headers */
342 for (i = 0; i < 4; i++) {
343 struct MD *mh;
344
345 if (!(mh = (struct MD *)Calloc(1, sizeof(struct MD)))) {
346 int j;
347
348 for (j = 0 ; j < i; j++) {
349 free((char *)cx->md[i]);
350 }
351 return -1;
352 }
353 mh->md_next = mh->md_prev = mh;
354 mh->md_dic = (struct DM *)0;
355 mh->md_flags = 0;
356 cx->md[i] = mh;
357 }
358 cx->dmprev = (struct DM *)0;
359 cx->qmprev = (struct DM *)0;
360 cx->nv = (struct NV *)0;
361 cx->ddpath = (struct DD **)0;
362 cx->kouhomode = (unsigned long)0;
363 cx->concmode = 0;
364 cx->litmode = (unsigned long *)Calloc(MAXLIT, sizeof(unsigned long));
365 cx->gram = &SG;
366 if (cx->litmode) {
367 for (i = 0; i < MAXLIT; i++) {
368 cx->litmode[i] = 0x87654321;
369 }
370 cx->poss_cont = 0;
371 #ifdef EXTENSION_NEW
372 cx->cx_gwt = (pointer)Calloc(1, sizeof(struct _rec));
373 if (cx->cx_gwt) {
374 struct _rec *gwt = (struct _rec *)cx->cx_gwt;
375 gwt->gwt_cx = -1; /* means no GetWordTextdic context
376 is available */
377 gwt->gwt_dicname = (unsigned char *)0;
378 cx->flags = CTX_LIVE | CTX_NODIC;
379 return 0;
380 }
381 free((char *)cx->litmode);
382 #else
383 cx->flags = CTX_LIVE | CTX_NODIC;
384 return 0;
385 #endif
386 }
387 return -1;
388 }
389
390 int
RkwCreateContext()391 RkwCreateContext()
392 {
393 int cx_num, i;
394 struct RkContext *newcx;
395
396 /* saisho no aki context wo mitsukeru */
397 for(cx_num = 0; cx_num < (int)now_context; cx_num++) {
398 if(!CX[cx_num].flags) {
399 /* create mount list headers */
400 if (fillContext(cx_num) == 0) {
401 return cx_num;
402 }
403 }
404 }
405 newcx = (RkContext *)realloc(CX, (size_t) sizeof(RkContext)
406 * (now_context+ADD_CONTEXT));
407 if (newcx) {
408 CX = newcx;
409 for (i = now_context ; i < (int)now_context + ADD_CONTEXT ; i++) {
410 CX[i].flags = (unsigned)0;
411 }
412 cx_num = now_context;
413 now_context += ADD_CONTEXT;
414 if (fillContext(cx_num) == 0) {
415 return cx_num;
416 }
417 }
418 return(-1);
419 }
420
421 int
RkwCloseContext(cx_num)422 RkwCloseContext(cx_num)
423 int cx_num;
424 {
425 struct RkContext *cx;
426 int i;
427
428 if (!(cx = RkGetContext(cx_num)))
429 return(-1);
430 /* terminate bunsetu henkan */
431 if (IS_XFERCTX(cx))
432 RkwEndBun(cx_num, 0);
433 _RkFreeDDP(cx->ddpath);
434 cx->ddpath = (struct DD **)0;
435 /* subete no jisho wo MD suru */
436 for (i = 0; i < 4; i++) {
437 struct MD *mh, *m, *n;
438
439 /* destroy mount list */
440 mh = cx->md[i];
441 if (mh) {
442 for (m = mh->md_next; m != mh; m = n) {
443 n = m->md_next;
444 (void)_RkUmountMD(cx, m);
445 };
446 (void)free((char *)mh);
447 cx->md[i] = (struct MD *)0;
448 };
449 };
450 cx->dmprev = (struct DM *)0;
451 cx->qmprev = (struct DM *)0;
452 /* convertion table */
453 if (cx->litmode) {
454 (void)free((char *)cx->litmode);
455 cx->litmode = (unsigned long *)0;
456 }
457 cx->flags = 0;
458
459 /* free grammatical dictionary */
460 cx->gram->refcount--;
461 if (cx->gram->refcount == 0 && cx->gram != &SG) {
462 RkCloseGram(cx->gram->gramdic);
463 free((char *)cx->gram);
464 }
465 cx->gram = (struct RkGram *)0;
466
467 #ifdef EXTENSION_NEW
468 if (cx->cx_gwt) {
469 struct _rec *gwt = (struct _rec *)cx->cx_gwt;
470 if (gwt) {
471 (void)RkwCloseContext(gwt->gwt_cx);
472 if (gwt->gwt_dicname)
473 (void)free((char *)gwt->gwt_dicname);
474 (void)free((char *)gwt);
475 };
476 cx->cx_gwt = (pointer)0;
477 };
478 freeTdn(cx);
479 #endif
480 return 0;
481 }
482 /* RkDuplicateContext
483 * onaji naiyou no context wo sakuseisuru
484 */
485 int RkwDuplicateContext pro((int));
486
487 int
RkwDuplicateContext(cx_num)488 RkwDuplicateContext(cx_num)
489 int cx_num;
490 {
491 struct RkContext *sx;
492 int dup = -1;
493
494 dup = RkwCreateContext();
495 if (dup >= 0) {
496 int i;
497 struct RkContext *dx;
498
499 sx = RkGetContext(cx_num);
500 if (sx) {
501 dx = RkGetContext(dup);
502
503 /* use the same grammatical information */
504 dx->gram = sx->gram;
505 dx->gram->refcount++;
506 if (!(sx->flags & CTX_NODIC)) {
507 dx->flags &= ~CTX_NODIC;
508 }
509
510 /* copy the mount list */
511 for (i = 0; i < 4; i++) {
512 struct MD *mh, *md;
513
514 /* should mount dictionaries in reverse order */
515 mh = sx->md[i];
516 for (md = mh->md_prev; md != mh; md = md->md_prev)
517 (void)_RkMountMD(dx, md->md_dic, md->md_freq,
518 md->md_flags & MD_WRITE, 0);
519 };
520 dx->ddpath = _RkCopyDDP(sx->ddpath);
521 if (sx->litmode && dx->litmode)
522 for (i = 0; i < MAXLIT; i++)
523 dx->litmode[i] = sx->litmode[i];
524 } else {
525 RkwCloseContext(dup);
526 return -1;
527 }
528 }
529 return(dup);
530 }
531
532 /* RkMountDic: append the specified dictionary at the end of the mount list */
533 int
RkwMountDic(cx_num,name,mode)534 RkwMountDic(cx_num, name, mode)
535 int cx_num; /* context specified */
536 char *name; /* the name of dictonary */
537 int mode; /* mount mode */
538 {
539 struct RkContext *cx;
540 int firsttime;
541
542 if (!name)
543 return(-1);
544 cx = RkGetContext(cx_num);
545 if (cx) {
546 struct DM *dm, *qm;
547
548 firsttime = (cx->flags & CTX_NODIC) ? 1 : 0;
549 if (firsttime) { /* �ǽ�˥ޥ����*���褦��*������ߤ� */
550 cx->flags &= ~CTX_NODIC;
551 }
552
553 dm = _RkSearchDicWithFreq(cx->ddpath, name, &qm);
554 if (dm) {
555 struct MD *mh = cx->md[dm->dm_class];
556 struct MD *md, *nd;
557 int count = 0;
558
559 /* search the dictionary */
560 for (md = mh->md_next; md != mh; md = nd) {
561 nd = md->md_next;
562 if (md->md_dic == dm) { /* already mounted */
563 /* cancel the previous unmount */
564 if (md->md_flags & MD_UPEND)
565 md->md_flags &= ~MD_UPEND;
566 count++;
567 };
568 };
569 if (!count) {
570 return _RkMountMD(cx, dm, qm, mode, firsttime);
571 }
572 }
573 }
574 return(-1);
575 }
576 /* RkUnmountDic: removes the specified dictionary from the mount list */
577 int
RkwUnmountDic(cx_num,name)578 RkwUnmountDic(cx_num, name)
579 int cx_num;
580 char *name;
581 {
582 struct RkContext *cx;
583 int i;
584
585 if (!name)
586 return(-1);
587 cx = RkGetContext(cx_num);
588 if (cx) {
589 for (i = 0; i < 4; i++) {
590 struct MD *mh = cx->md[i];
591 struct MD *md, *nd;
592
593 for (md = mh->md_next; md != mh; md = nd) {
594 struct DM *dm = md->md_dic;
595 char *ename;
596
597 ename = md->md_freq ? md->md_freq->dm_nickname : dm->dm_nickname;
598 nd = md->md_next;
599 if (!STRCMP(ename, name)) {
600 _RkUmountMD(cx, md);
601 }
602 }
603 }
604 return(0);
605 }
606 return(-1);
607 }
608
609 /* RkRemountDic: relocate the specified dictionary among the mount list */
610 int
RkwRemountDic(cx_num,name,mode)611 RkwRemountDic(cx_num, name, mode)
612 int cx_num; /* context specified */
613 char *name; /* the name of dictonary */
614 int mode; /* mount mode */
615 {
616 struct RkContext *cx;
617 int i, isfound = 0;
618 char *ename;
619
620 if (!name)
621 return(-1);
622 cx = RkGetContext(cx_num);
623 if (cx) {
624 for (i = 0; i < 4; i++) {
625 struct MD *mh = cx->md[i];
626 struct MD *md, *pd;
627
628 /* do in reverse order */
629 for (md = mh->md_prev; md != mh; md = pd) {
630 struct DM *dm = md->md_dic;
631
632 ename = md->md_freq ? md->md_freq->dm_nickname : dm->dm_nickname;
633 pd = md->md_prev;
634 if (!STRCMP(ename, name)) {
635 /* remove from mount list */
636 md->md_prev->md_next = md->md_next;
637 md->md_next->md_prev = md->md_prev;
638 /* insert according to the mode */
639 if (!mode) { /* sentou he */
640 md->md_next = mh->md_next;
641 md->md_prev = mh;
642 mh->md_next->md_prev = md;
643 mh->md_next = md;
644 } else { /* saigo he */
645 md->md_next = mh;
646 md->md_prev = mh->md_prev;
647 mh->md_prev->md_next = md;
648 mh->md_prev = md;
649 };
650 isfound++;
651 };
652 };
653 };
654 if (isfound)
655 return(0);
656 };
657 return(-1);
658 }
659
660 /* RkGetDicList: collects the names of the mounted dictionaies */
661 int
RkwGetMountList(cx_num,mdname,maxmdname)662 RkwGetMountList(cx_num, mdname, maxmdname)
663 int cx_num;
664 char *mdname;
665 int maxmdname;
666 {
667 struct RkContext *cx;
668 struct MD *mh, *md;
669 int p, i, j;
670 int count = -1;
671
672 cx = RkGetContext(cx_num);
673 if (cx) {
674 i = count = 0;
675 for (p = 0; p < 4; p++) {
676 mh = cx->md[p];
677 for (md = mh->md_next; md != mh; md = md->md_next) {
678 struct DM *dm = md->md_dic;
679 char *name;
680
681 if (md->md_flags & (MD_MPEND|MD_UPEND)) {
682 continue;
683 };
684 name = md->md_freq ? md->md_freq->dm_nickname : dm->dm_nickname;
685 j = i + strlen(name) + 1;
686 if (j + 1 < maxmdname) {
687 if (mdname) {
688 (void)strcpy(mdname + i, name);
689 }
690 i = j;
691 count++;
692 };
693 };
694 };
695 if (i + 1 < maxmdname && mdname)
696 mdname[i++] = (char)0;
697 };
698 return(count);
699 }
700
701 /* RkGetDicList: collects the names of dictionary */
702
703 struct dics {
704 char *nickname, *dicname;
705 int dictype;
706 };
707
708 static int diccmp pro((const struct dics *, const struct dics *));
709
710 static int
diccmp(a,b)711 diccmp(a, b)
712 const struct dics *a, *b;
713 {
714 int res;
715
716 res = strcmp(a->nickname, b->nickname);
717 if (res == 0) {
718 res = strcmp(a->dicname, b->dicname);
719 if (res == 0) {
720 if (a->dictype == b->dictype) {
721 res = 0;
722 }
723 else if (a->dictype == DF_FREQDIC) {
724 res = -1;
725 }
726 else if (b->dictype == DF_FREQDIC) {
727 res = 1;
728 }
729 else if (a->dictype == DF_PERMDIC) {
730 res = -1;
731 }
732 else if (b->dictype == DF_PERMDIC) {
733 res = 1;
734 }
735 else {
736 res = 0;
737 }
738 }
739 }
740 return res;
741 }
742
743 int
RkwGetDicList(cx_num,mdname,maxmdname)744 RkwGetDicList(cx_num, mdname, maxmdname)
745 int cx_num;
746 char *mdname;
747 int maxmdname;
748 {
749 struct RkContext *cx;
750 struct DD **ddp, *dd;
751 struct DF *df, *fh;
752 struct DM *dm, *mh;
753 int i, j, k, n;
754 int count = -1;
755 struct dics *diclist;
756
757 /* �ޤ���������� */
758 if ((cx = RkGetContext(cx_num)) && (ddp = cx->ddpath)) {
759 count = 0;
760 for (i = 0; (dd = ddp[i]) != (struct DD *)0 ; i++) {
761 fh = &dd->dd_files;
762 for (df = fh->df_next; df != fh; df = df->df_next) {
763 mh = &df->df_members;
764 for (dm = mh->dm_next; dm != mh; dm = dm->dm_next) {
765 count++;
766 }
767 }
768 }
769 /* ����ꥹ�Ȥ������ malloc ���� */
770 diclist = (struct dics *)malloc(count * sizeof(struct dics));
771 if (diclist) {
772 struct dics *dicp = diclist, *prevdicp = (struct dics *)0;
773
774 for (i = 0 ; (dd = ddp[i]) != (struct DD *)0 ; i++) {
775 fh = &dd->dd_files;
776 for (df = fh->df_next; df != fh; df = df->df_next) {
777 mh = &df->df_members;
778 for (dm = mh->dm_next; dm != mh; dm = dm->dm_next) {
779 dicp->nickname = dm->dm_nickname;
780 dicp->dicname = dm->dm_dicname;
781 dicp->dictype = df->df_type;
782 dicp++;
783 }
784 }
785 }
786 qsort(diclist, count, sizeof(struct dics),
787 (int (*) pro((const void *, const void *)))diccmp);
788
789 n = count;
790 for (i = j = 0, dicp = diclist ; i < n ; i++, dicp++) {
791 if (prevdicp && !strcmp(prevdicp->nickname, dicp->nickname)) {
792 /* prev �Ⱥ��μ���Ȥ� nickname �����פ��Ƥ����� */
793 count--;
794 }
795 else {
796 k = j + strlen(dicp->nickname) + 1;
797 if (k + 1 < maxmdname) {
798 if (mdname) {
799 (void)strcpy(mdname + j, dicp->nickname);
800 j = k;
801 }
802 }
803 prevdicp = dicp;
804 }
805 }
806 if (j + 1 < maxmdname && mdname) {
807 mdname[j++] = 0;
808 }
809 free((char *)diclist);
810 }
811 else {
812 count = -1; /* ��äѤ����Τʿ���ʬ����ʤ��ä� */
813 }
814 }
815 return(count);
816 }
817
818 /* RkGetDirList: collects the names of directories */
819 int
RkwGetDirList(cx_num,ddname,maxddname)820 RkwGetDirList(cx_num, ddname, maxddname)
821 int cx_num;
822 char *ddname;
823 int maxddname;
824 {
825 struct RkContext *cx;
826 struct DD **ddp, *dd;
827 int p, i, j;
828 int count = -1;
829
830 if ((cx = RkGetContext(cx_num)) && (ddp = cx->ddpath)) {
831 i = count = 0;
832 for (p = 0; (dd = ddp[p]) != (struct DD *)0 ; p++) {
833 j = i + strlen(dd->dd_name) + 1;
834 if (j + 1 < maxddname) {
835 if (ddname)
836 (void)strcpy(ddname + i, dd->dd_name);
837 i = j;
838 count++;
839 };
840 };
841 if (i + 1 < maxddname && ddname)
842 ddname[i++] = (char)0;
843 };
844 return(count);
845 }
846
847 /* RkDefineDic
848 * mount the dictionary onto the specified context.
849 */
850 int
RkwDefineDic(cx_num,name,word)851 RkwDefineDic(cx_num, name, word)
852 int cx_num;
853 char *name;
854 Wchar *word;
855 {
856 struct RkContext *cx;
857 int i;
858
859 if ((cx = RkGetContext(cx_num)) && word && name) {
860 char *prevname = (char *)0;
861
862 if (cx->dmprev)
863 prevname = cx->dmprev->dm_nickname;
864 if (cx->qmprev)
865 prevname = cx->qmprev->dm_nickname;
866
867 if (prevname && !STRCMP(prevname, name))
868 return(DST_CTL(cx->dmprev, cx->qmprev, DST_DoDefine, word,
869 cx->gram->gramdic));
870 else {
871 for (i = 0; i < 4; i++) {
872 struct MD *mh = cx->md[i];
873 struct MD *md, *nd;
874
875 for (md = mh->md_next; md != mh; md = nd) {
876 struct DM *dm = md->md_dic;
877 struct DM *qm = md->md_freq;
878 char *dname = (char *)0;
879
880 if (dm)
881 dname = dm->dm_nickname;
882 if (qm)
883 dname = qm->dm_nickname;
884
885 if (dname) {
886 if (!STRCMP(dname, name)) {
887 cx->dmprev = dm;
888 cx->qmprev = qm;
889 return(DST_CTL(dm, qm, DST_DoDefine, word, cx->gram->gramdic));
890 }
891 }
892 nd = md->md_next;
893 }
894 }
895 }
896 }
897 return(-1);
898 }
899
900
901 /* RkDeleteDic
902 * mount the dictionary onto the specified context.
903 */
904 int
RkwDeleteDic(cx_num,name,word)905 RkwDeleteDic(cx_num, name, word)
906 int cx_num;
907 char *name;
908 Wchar *word;
909 {
910 struct RkContext *cx;
911 int i;
912
913 if ((cx = RkGetContext(cx_num)) && name) {
914 char *prevname = (char *)0;
915
916 if (cx->dmprev)
917 prevname = cx->dmprev->dm_nickname;
918 if (cx->qmprev)
919 prevname = cx->qmprev->dm_nickname;
920
921 if (prevname && !STRCMP(prevname, name))
922 return(DST_CTL(cx->dmprev, cx->qmprev, DST_DoDelete, word,
923 cx->gram->gramdic));
924 else {
925 for (i = 0; i < 4; i++) {
926 struct MD *mh = cx->md[i];
927 struct MD *md, *nd;
928
929 for (md = mh->md_next; md != mh; md = nd) {
930 struct DM *dm = md->md_dic;
931 struct DM *qm = md->md_freq;
932 char *dname = (char *)0;
933
934 if (dm)
935 dname = dm->dm_nickname;
936 if (qm)
937 dname = qm->dm_nickname;
938
939 if (dname) {
940 if (!STRCMP(dname, name)) {
941 cx->dmprev = dm;
942 cx->qmprev = qm;
943 return(DST_CTL(dm, qm, DST_DoDelete, word, cx->gram->gramdic));
944 }
945 }
946 nd = md->md_next;
947 }
948 }
949 }
950 }
951 return(-1);
952 }
953
954 #ifdef STANDALONE /* The following code is as simulating the code in
955 lib/RKC API. In case STANDALONE, it becomes possible for libRK to be
956 linked with libcanna directly. */
957
958 int RkwSetAppName pro((int, char *));
959
960 int
RkwSetAppName(Context,name)961 RkwSetAppName(Context, name)
962 int Context;
963 char *name;
964 {
965 return 0;
966 }
967
968 char *RkwGetServerName pro((void));
969
970 char *
RkwGetServerName()971 RkwGetServerName()
972 {
973 return (char *)NULL;
974 }
975
976 int RkwGetProtocolVersion pro((int *, int *));
977
978 int
RkwGetProtocolVersion(majorp,minorp)979 RkwGetProtocolVersion(majorp, minorp)
980 int *majorp, *minorp;
981 {
982 *majorp = CANNA_MAJOR_MINOR / 1000;
983 *minorp = CANNA_MAJOR_MINOR % 1000;
984 return 0;
985 }
986
987 int RkwGetServerVersion(int *, int *);
988
989 int
RkwGetServerVersion(majorp,minorp)990 RkwGetServerVersion(majorp, minorp)
991 int *majorp, *minorp;
992 {
993 *majorp = CANNA_MAJOR_MINOR / 1000;
994 *minorp = CANNA_MAJOR_MINOR % 1000;
995 return 0;
996 }
997
998 int
RkwSetUserInfo(user,group,topdir)999 RkwSetUserInfo(user, group, topdir)
1000 char *user, *group, *topdir;
1001 {
1002 return 1;
1003 }
1004
1005 #endif /* STANDALONE */
1006