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