diff Wnn/jserver/jikouho_d.c @ 0:bbc77ca4def5

initial import
author Yoshiki Yazawa <yaz@cc.rim.or.jp>
date Thu, 13 Dec 2007 04:30:14 +0900
parents
children b605a0e60f5b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wnn/jserver/jikouho_d.c	Thu Dec 13 04:30:14 2007 +0900
@@ -0,0 +1,853 @@
+/*
+ *  $Id: jikouho_d.c,v 1.6 2002/05/12 22:51:16 hiroo Exp $
+ */
+
+/*
+ * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
+ * This file is part of FreeWnn.
+ * 
+ * Copyright Kyoto University Research Institute for Mathematical Sciences
+ *                 1987, 1988, 1989, 1990, 1991, 1992
+ * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
+ * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992
+ * Copyright FreeWnn Project 1999, 2000, 2002
+ *
+ * Maintainer:  FreeWnn Project   <freewnn@tomo.gr.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/************************************************
+ *      大文節次候補取りだし                    *
+ ************************************************/
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include        <stdio.h>
+#include        <ctype.h>
+#if STDC_HEADERS
+#  include	<stdlib.h>
+#else
+#  if HAVE_MALLOC_H
+#    include <malloc.h>
+#  endif
+#endif /* STDC_HEADERS */
+
+#include        "commonhd.h"
+#include        "de_header.h"
+#include        "jdata.h"
+#include        "fzk.h"
+#include        "kaiseki.h"
+
+#ifdef  CONVERT_from_TOP
+static void sbn_set (), sons_set ();
+#endif /* CONVERT_from_TOP */
+
+static void dsd_hyouka (), cnt_sbn (), cnt_dbn ();
+static int cmp_dsd_dbn (), jkt_dbn (), jkt_sbjunjo (), set_jkt_dai (), zen_sbn (), cnt_par (), cnt_son ();
+static struct JKT_SBN *jkt_que_reorder ();
+
+static int yomi_sno_tmp;
+
+/*
+ * jkt_get_dai : 次候補 all 取りだし (大文節)
+ */
+int
+#ifdef  NO_FZK
+jkt_get_dai (yomi_sno, yomi_eno, beginvect, endvect, endvect1, nmax, dsd_dbn)
+#else
+jkt_get_dai (yomi_sno, yomi_eno, beginvect, fzkchar, endvect, endvect1, nmax, dsd_dbn)
+#endif                          /* NO_FZK */
+     int yomi_sno;
+     int yomi_eno;
+     int beginvect;             /* 前端ベクタ(-1:文節先頭、-2:なんでも)品詞No. */
+#ifndef NO_FZK
+     w_char *fzkchar;
+#endif /* NO_FZK */
+     int endvect;               /* 終端ベクタ */
+     int endvect1;              /* 終端ベクタ */
+     int nmax;                  /* 1大文節中の最大小文節数 */
+     struct DSD_DBN **dsd_dbn;
+{
+  register int i;
+  register int cnt;
+  struct JKT_DBN *rjkt_dbn = 0;
+  register struct DSD_DBN *dbn;
+  int divid;
+
+  if (c_env->fzk_fid == -1)
+    {
+      wnn_errorno = WNN_FZK_FILE_NO_LOAD;
+      return (-1);
+    }
+  ft = (struct FT *) files[c_env->fzk_fid].area;
+  if ((cnt = jkt_dbn (yomi_sno, yomi_eno, beginvect,
+#ifndef NO_FZK
+                      fzkchar,
+#endif /* NO_FZK */
+                      endvect, endvect1, nmax, &rjkt_dbn)) < 0)
+    {
+      init_work_areas ();
+      return (-1);
+    }
+  if ((cnt = dbn_set (dsd_dbn, rjkt_dbn)) < 0)
+    {
+      init_work_areas ();
+      return (-1);
+    }
+  for (dbn = *dsd_dbn, i = cnt; i > 0; i--, dbn++)
+    {
+      dsd_hyouka (dbn);
+      if ((divid = get_jkt_status (dbn->sbn->kangovect, beginvect,
+#ifndef NO_FZK
+                                   fzkchar,
+#endif /* NO_FZK */
+                                   &(dbn->sbn->status))) != 0)
+        dbn->v_jc = DIVID_HYOUKA (dbn->v_jc, divid);
+    }
+  /* SORT */
+  qsort ((char *) *dsd_dbn, cnt, sizeof (struct DSD_DBN), cmp_dsd_dbn);
+  return (cnt);
+}
+
+static int
+cmp_dsd_dbn (dbn1, dbn2)
+     struct DSD_DBN *dbn1;
+     struct DSD_DBN *dbn2;
+{
+  return (dbn2->v_jc - dbn1->v_jc);
+}
+
+static void
+dsd_hyouka (dbn)
+     struct DSD_DBN *dbn;
+{
+  struct DSD_SBN *sbn;
+  int len;                      /* 大文節長 */
+  int son_v = 0;
+  register int j_c;
+  register struct DSD_SBN *s_p;
+  int i;
+
+  sbn = dbn->sbn;
+  j_c = sbn->bun_jc;
+  len = j_c - dbn->bun_m + 1;
+
+  for (i = 0, s_p = sbn; i < dbn->sbncnt; s_p++, i++)
+    {
+      son_v += s_p->v_jc;
+    }
+
+  dbn->v_jc = hyoka_dbn (son_v, dbn->sbncnt, len);
+}
+
+/*******************/
+
+static int
+#ifdef  NO_FZK
+jkt_dbn (yomi_sno, yomi_eno, beginvect, endvect, endvect1, nmax, rjkt_dbn)
+#else
+jkt_dbn (yomi_sno, yomi_eno, beginvect, fzkchar, endvect, endvect1, nmax, rjkt_dbn)
+#endif                          /* NO_FZK */
+     int yomi_sno;
+     int yomi_eno;
+     int beginvect;             /* 前端ベクタ(-1:文節先頭、-2:なんでも)品詞No. */
+#ifndef NO_FZK
+     w_char *fzkchar;
+#endif /* NO_FZK */
+     int endvect;               /* 終端ベクタ */
+     int endvect1;              /* 終端ベクタ */
+     register int nmax;         /* 1大文節中の最大小文節数 */
+     struct JKT_DBN **rjkt_dbn; /* 次候補解析結果 */
+{
+  register struct JKT_SBN **sb_que_head;        /* 小文節解析結果 */
+  int tmp;                      /* 次候補ベクター数 */
+  struct JKT_SBN *db_tmp;
+  register struct JKT_SBN *sb_one;
+  struct JKT_SBN *sbn_tmp;
+  register struct JKT_SBN **sb_que_newcomer;
+  struct JKT_DBN *jktdbn = 0;
+  int dbncnt = 0;
+#ifndef NO_KANA
+  int gijiflag = 0;             /* 疑似文節を作ったか:最初の小文節のみ */
+#endif /* NO_KANA */
+
+  yomi_sno_tmp = yomi_sno;
+
+  sb_que_head = &db_tmp;
+  *sb_que_head = NULL;
+
+  if ((tmp = zen_sbn (yomi_sno, yomi_eno, endvect, endvect1, sb_que_head, 1, (struct JKT_SBN *) 0
+#ifndef NO_KANA
+                      , &gijiflag
+#endif /* NO_KANA */
+       )) <= 0)
+    return (tmp);
+
+  while (*sb_que_head != NULL)
+    {
+      sb_one = *sb_que_head;
+      *sb_que_head = sb_one->lnk_br;
+      if (nmax > sb_one->kbcnt && yomi_eno > sb_one->j_c + 1)
+        {
+          sb_que_newcomer = &sbn_tmp;
+          *sb_que_newcomer = NULL;
+          tmp = zen_sbn (sb_one->j_c + 1, yomi_eno, sb_one->kangovect, WNN_VECT_NO, sb_que_newcomer, sb_one->kbcnt + 1, sb_one
+#ifndef NO_KANA
+                         , 0
+#endif /* NO_KANA */
+            );
+          if (tmp < 0)
+            {
+              return (-1);      /* ERROR */
+            }
+          else if (tmp > 0)
+            {
+              sb_one->reference += tmp;
+              if (*sb_que_head != 0)
+                *sb_que_head = jkt_que_reorder (*sb_que_head, *sb_que_newcomer);
+              else
+                *sb_que_head = *sb_que_newcomer;
+            }
+          else
+            {
+              freejktsbn (sb_one);
+            }
+        }
+      else if (yomi_eno == sb_one->j_c + 1)
+        {
+          if (set_jkt_dai (rjkt_dbn, &jktdbn, sb_one) < 0)
+            return (-1);
+          dbncnt++;
+        }
+    }
+#ifndef NO_KANA
+/* ひらがな候補 */
+  if (gijiflag == 0)
+    {
+      if ((sb_one = get_hira_kouho (&db_tmp, yomi_sno, yomi_eno)) < (struct JKT_SBN *) 0)
+        return (-1);
+
+      if (sb_one > (struct JKT_SBN *) 0)
+        {
+          sb_one->parent = 0;
+          sb_one->bend_m = yomi_sno;
+          sb_one->kbcnt = 1;
+          if (set_jkt_dai (rjkt_dbn, &jktdbn, sb_one) < 0)
+            return (-1);
+          dbncnt++;
+        }
+    }
+#endif /* NO_KANA */
+
+  return (dbncnt);
+}
+
+/* 前(beginvect,fzkchar)と接続できるか調べ、
+        接続できるとき          1
+        大文節の先頭の時        0
+        接続できないとき        -1
+   を返す
+        get_status 参照
+*/
+
+int
+#ifdef  NO_FZK
+get_jkt_status (kangovect, beginvect, status)
+#else
+get_jkt_status (kangovect, beginvect, fzkchar, status)
+#endif                          /* NO_FZK */
+     int kangovect;
+     int beginvect;
+#ifndef NO_FZK
+     w_char *fzkchar;
+#endif /* NO_FZK */
+     short *status;
+{
+  extern int _status;
+  _status = 0;
+  return (get_status (kangovect, beginvect,
+#ifndef NO_FZK
+                      fzkchar,
+#endif /* NO_FZK */
+                      status));
+}
+
+/*
+int
+get_dsd_status(kangovect, beginvect, fzkchar, status)
+int     kangovect;
+int     beginvect;
+w_char  *fzkchar;
+int     *status;
+{
+    if (zentan_able(kangovect, beginvect, fzkchar) == YES) {
+        if (beginvect == WNN_ALL_HINSI) {
+            if (kan_ckvt(sentou_no, kangovect) == WNN_CONNECT_BK) {
+                *status = WNN_SENTOU;
+            } else {
+                *status = WNN_NOT_CONNECT;
+                return (-1);
+            }
+        } else if (beginvect == WNN_BUN_SENTOU) {
+                *status = WNN_SENTOU;
+        } else {
+            if ((fzkchar == NULL || *fzkchar == NULL) && beginvect == sentou_no)
+                *status = WNN_SENTOU;
+            else
+                *status = WNN_CONNECT;
+                return (1);
+        }
+    } else if (kan_ckvt(sentou_no, kangovect) == WNN_CONNECT_BK) {
+            sb_one->status = WNN_SENTOU;
+    } else {
+            *status = WNN_NOT_CONNECT;
+            return (-1);
+    }
+    return(0);
+}
+*/
+
+/* 小文節の並び替え 長さとベクタでソートする */
+/* que の先頭を返す */
+static struct JKT_SBN *
+jkt_que_reorder (que, new)
+     register struct JKT_SBN *que, *new;
+{
+  struct JKT_SBN *que_sv;
+  register struct JKT_SBN *tmp;
+  register struct JKT_SBN *next;
+
+  if (new == 0)
+    return (que);
+  if (jkt_sbjunjo (que, new) < 0)
+    {
+      que_sv = new;
+    }
+  else
+    que_sv = que;
+
+  while (new != NULL)
+    {
+      next = new->lnk_br;
+      if (jkt_sbjunjo (que, new) < 0)
+        {
+          /* NEW が前 */
+          tmp = que;
+          que = new;
+          que->lnk_br = tmp;
+          new = next;
+          continue;
+        }
+      /* QUE が前 */
+      while ((jkt_sbjunjo (que, new) > 0) && que->lnk_br != NULL)
+        que = (que->lnk_br);
+      tmp = que->lnk_br;
+      /* QUE の後にNEW */
+      que->lnk_br = new;
+      new->lnk_br = tmp;
+      new = next;
+    }
+  return (que_sv);
+}
+
+/* que と new の順序
+        1: que が前
+        0: que の後に new
+        -1:new が前
+XXXXX   -2:同一順位 */
+static int
+jkt_sbjunjo (que, new)
+     struct JKT_SBN *que, *new;
+{
+  if (new == 0)
+    return (1);
+  if (que->j_c > new->j_c)
+    return (-1);
+  if (que->j_c < new->j_c)
+    {
+      if (que->lnk_br == 0)
+        return (0);
+      if (que->lnk_br->j_c > new->j_c)
+        return (0);
+      if (que->lnk_br->j_c < new->j_c)
+        return (1);
+      if (que->lnk_br->kangovect > new->kangovect)
+        return (0);
+      return (1);
+    }
+  if (que->kangovect == new->kangovect)
+    return (0);                 /* return (-2); */
+  if (que->kangovect > new->kangovect)
+    return (-1);
+  if (que->lnk_br == 0)
+    return (0);
+  if (que->lnk_br->j_c > new->j_c)
+    return (0);
+  if (que->lnk_br->kangovect > new->kangovect)
+    return (0);
+  return (1);
+}
+
+
+/* 文節の先頭になれれば、大文節の候補をセットする */
+static int
+set_jkt_dai (rjkt_dbn, jktdbn, sbn)
+     struct JKT_DBN **rjkt_dbn;
+     register struct JKT_DBN **jktdbn;
+     register struct JKT_SBN *sbn;
+{
+  struct JKT_DBN *getjktdbn ();
+
+  if (*jktdbn != 0)
+    {
+      if (((*jktdbn)->lnk_br = getjktdbn ()) == 0)
+        return (-1);
+      (*jktdbn) = (*jktdbn)->lnk_br;
+    }
+  else
+    {
+      if ((*rjkt_dbn = *jktdbn = getjktdbn ()) == 0)
+        return (-1);
+    }
+  (*jktdbn)->j_c = sbn->j_c;
+  (*jktdbn)->sbn_cnt = sbn->kbcnt;
+  (*jktdbn)->lnk_br = 0;
+  (*jktdbn)->sbn = sbn;
+  (*jktdbn)->bend_m = yomi_sno_tmp;
+  return (0);
+}
+
+static int
+zen_sbn (yomi_sno, yomi_eno, endvect, endvect1, tjktsbn, bnst_num, parent
+#ifndef NO_KANA
+         , gijiflagp
+#endif                          /* NO_KANA */
+  )
+     int yomi_sno;
+     int yomi_eno;
+     int endvect;               /* 終端ベクタ */
+     int endvect1;              /* 終端ベクタ */
+     struct JKT_SBN **tjktsbn;  /* 小文節解析結果 */
+     int bnst_num;              /* これまでに解析した小文節数 */
+     struct JKT_SBN *parent;    /* 親の幹語ノード */
+#ifndef NO_KANA
+     int *gijiflagp;
+#endif /* NO_KANA */
+{
+  register int fzkcnt, ii, jktcnt;
+  register int i,               /* 幹語の終わりのインデックス */
+    j;                          /* 文節始めのインデックス */
+  struct JKT_SBN *jktsbn_top = 0;
+  struct ICHBNP *ichbnpbp;
+  struct JKT_SBN *gijisbn_top;
+  int get_giji_flg = -1;        /* 擬似文節を作れたか */
+  int cnt;
+#ifndef NO_KANA
+  struct JKT_SBN *jktsbn;
+  int index_tmp;
+  struct fzkkouho *fzkptr;
+  int *vector1;
+#endif
+
+#ifndef NO_KATA
+  struct JKT_SBN *get_kata_kouho ();
+#endif
+  struct JKT_SBN *get_hira_kouho ();
+  struct SYO_BNSETSU *giji_sbn;
+  struct SYO_BNSETSU *getsbnsp ();
+
+  if (yomi_sno == yomi_eno)
+    return (NOTHING);
+
+  if (fzk_ckvt (endvect) == NO && fzk_ckvt (endvect1) == NO)
+    return (NOTHING);
+  fzkcnt = fzk_kai (&bun[yomi_sno], &bun[yomi_eno], endvect, endvect1, &ichbnpbp);
+  if (fzkcnt <= 0)
+    return (fzkcnt);            /* ERROR */
+  for (ii = 0; ii < fzkcnt; ii++)
+    getfzkoh (ichbnpbp, ii)->offset += yomi_sno;
+
+
+  for (ii = 0; ii < fzkcnt; ii++)
+    {
+      i = getfzkoh (ichbnpbp, ii)->offset;
+      if (jmtp[i] == (struct jdata **) UN_KNOWN)        /* もう引いた? */
+        jmt_set (i);            /* 辞書引き */
+    }
+
+  j = j_max (ichbnpbp, fzkcnt);
+  j = (j >= yomi_eno) ? yomi_eno - 1 : j;
+
+  jktcnt = 0;
+
+#if     !defined(NO_KANA) && !defined(KOREAN)
+/* カタカナ疑似文節を取り出します */
+  if (gijiflagp != 0 && j < yomi_eno - 1)
+    {
+      for (ii = 0; ii < fzkcnt; ii++)
+        {                       /* 付属語 */
+          fzkptr = getfzkoh (ichbnpbp, ii);
+          if (bnst_num == 1)
+            vector1 = getfzkoh1 (ichbnpbp, ii)->vector;
+          else
+            vector1 = fzkptr->vector;
+          index_tmp = fzkptr->offset;
+          if ((jktsbn = get_kata_kouho (&jktsbn_top, yomi_sno, yomi_eno, fzkptr->offset, fzkptr->vector, vector1, ii)) < (struct JKT_SBN *) 0)
+
+            return (-1);
+          if (jktsbn > (struct JKT_SBN *) 0)
+            {
+              jktsbn->parent = parent;
+              jktsbn->bend_m = yomi_sno;
+              jktsbn->kbcnt = bnst_num;
+              jktcnt++;
+            }
+        }                       /* 付属語 */
+    }
+#endif /* !defined(NO_KANA) && !defined(KOREAN) */
+  if ((giji_sbn = getsbnsp ()) == NO)
+    return (-1);
+  gijisbn_top = 0;
+  giji_sbn->bend_m = yomi_sno;
+  if (getgiji (yomi_sno, yomi_eno, giji_sbn, ichbnpbp, fzkcnt, bnst_num) >= 0)
+    {
+      if (giji_sbn->hinsi_fk != katakanago_no && giji_sbn->hinsi_fk != giji_no && giji_sbn->hinsi_fk != fuzokugo_no)
+        {
+          if (get_zen_giji (giji_sbn, &gijisbn_top) < 0)
+            return (-1);
+          gijisbn_top->parent = parent;
+          gijisbn_top->kbcnt = bnst_num;
+          get_giji_flg = giji_sbn->j_c;
+#ifndef NO_KANA
+          if (gijiflagp != 0 && giji_sbn->j_c == yomi_eno - 1)
+            *gijiflagp = 1;
+#endif /* NO_KANA */
+          jktcnt++;
+        }
+    }
+  freesbn (giji_sbn);
+
+  if (gijisbn_top != 0)
+    {
+      if (get_giji_flg > j)
+        {
+          gijisbn_top->lnk_br = jktsbn_top;
+          jktsbn_top = gijisbn_top;
+          get_giji_flg = -1;
+        }
+    }
+
+  for (; j >= yomi_sno; j--)
+    {
+      /* 文節の長さ */
+      if (get_giji_flg == j)
+        {
+          gijisbn_top->lnk_br = jktsbn_top;
+          jktsbn_top = gijisbn_top;
+          get_giji_flg = -1;
+        }
+      if ((cnt = jkt_sbn_one (yomi_sno, j + 1, &jktsbn_top, bnst_num, parent, ichbnpbp, fzkcnt)) < 0)
+        return (-1);
+      jktcnt += cnt;
+
+    }
+  *tjktsbn = jktsbn_top;        /* 短いものから並べる */
+  freeibsp (ichbnpbp);
+  return (jktcnt);
+}
+
+struct DSD_DBN *
+get_dsd_dbn (cnt)
+     register int cnt;
+{
+  static struct DSD_DBN *m_dbn = 0;
+  static int md_cnt = 0;
+
+  if (md_cnt < cnt)
+    {
+      /* どんどんふくれる Jserver */
+      if (m_dbn)
+        free (m_dbn);
+      m_dbn = (struct DSD_DBN *) malloc (cnt * sizeof (struct DSD_DBN));
+      if (m_dbn == NULL)
+        {
+          /* 大きくなって天まで届け! */
+          wnn_errorno = WNN_JKTAREA_FULL;
+          error1 ("malloc err in dbn_set (at daibnsetsu jikouho).\n");
+          md_cnt = 0;
+          return ((struct DSD_DBN *) -1);
+        }
+      else
+        md_cnt = cnt;
+    }
+  return (m_dbn);
+}
+
+struct DSD_SBN *
+get_dsd_sbn (cnt)
+     register int cnt;
+{
+  static struct DSD_SBN *m_sbn = 0;
+  static int ms_cnt = 0;
+
+  if (ms_cnt < cnt)
+    {
+      if (m_sbn)
+        free (m_sbn);
+      m_sbn = (struct DSD_SBN *) malloc (cnt * sizeof (struct DSD_SBN));
+      if (m_sbn == NULL)
+        {
+          wnn_errorno = WNN_JKTAREA_FULL;
+          error1 ("malloc err in dbn_set (at daibnsetsu jikouho).\n");
+          ms_cnt = 0;
+          return ((struct DSD_SBN *) -1);
+        }
+      else
+        ms_cnt = cnt;
+    }
+  return (m_sbn);
+}
+
+int
+dbn_set (dsd_dbn, dbn)
+     struct DSD_DBN **dsd_dbn;
+     register struct JKT_DBN *dbn;
+{
+  register struct JKT_SBN *sbn;
+  register struct JKT_SONE *sone;
+  int i;
+#ifndef CONVERT_from_TOP
+  int j, son, par;
+#endif
+  struct JKT_DBN *next_dbn;
+
+  int cnt;
+  int dbn_cnt;
+  int sbn_cnt;
+  struct DSD_DBN *d_dbn;
+  struct DSD_SBN *d_sbn;
+  register struct DSD_SBN *p_sbn;
+  struct DSD_SBN *sv_sbn;
+
+  cnt_dbn (dbn, &cnt, &sbn_cnt);
+
+  if ((d_dbn = *dsd_dbn = get_dsd_dbn (cnt)) <= (struct DSD_DBN *) 0)
+    return (-1);
+  if ((sv_sbn = d_sbn = get_dsd_sbn (sbn_cnt)) <= (struct DSD_SBN *) 0)
+    return (-1);
+
+  while (dbn)
+    {
+      sbn = dbn->sbn;
+      cnt_sbn (sbn, &dbn_cnt, &sbn_cnt);
+      p_sbn = d_sbn = sv_sbn;
+      sv_sbn += sbn_cnt;
+      for (i = 0; i < dbn_cnt; i++)
+        {
+          d_dbn->bun_m = dbn->bend_m;
+          d_dbn->bun_jc = dbn->j_c;
+          d_dbn->sbncnt = dbn->sbn_cnt;
+          d_dbn->sbn = p_sbn;
+          p_sbn += dbn->sbn_cnt;
+          d_dbn++;
+        }
+#ifdef  CONVERT_from_TOP
+      sbn_set (dbn, &d_sbn, sone, dbn->sbn);
+
+      next_dbn = dbn->lnk_br;
+      freejktdbn (dbn);
+      dbn = next_dbn;
+#else /* CONVERT_from_TOP */
+      for (sbn = dbn->sbn; sbn != 0; sbn = sbn->parent, d_sbn++)
+        {
+          son = cnt_son (dbn->sbn, sbn);
+          par = cnt_par (sbn);
+          p_sbn = d_sbn;
+          for (j = 0; j < son; j++)
+            {
+              for (sone = sbn->sbn; sone != 0; sone = sone->lnk_br)
+                {
+                  for (i = 0; i < par; i++)
+                    {
+                      p_sbn->bun_m = sbn->bend_m;
+                      p_sbn->bun_jc = sbn->j_c;
+                      p_sbn->i_jc = sone->i_jc;
+                      p_sbn->jentptr = sone->jentptr;
+                      p_sbn->t_jc = sone->t_jc;
+                      p_sbn->hinsi = sone->hinsi_fk;
+                      p_sbn->kangovect = sbn->kangovect;
+                      p_sbn->v_jc = sone->v_jc;
+                      p_sbn->status_bkwd = sone->status_bkwd;
+                      if (sbn->status == WNN_NOT_CONNECT && sone->jentptr == 0)
+                        p_sbn->status = WNN_GIJI;
+                      else
+                        p_sbn->status = sbn->status;
+                      p_sbn += dbn->sbn_cnt;
+                    }
+                }
+            }
+        }
+      next_dbn = dbn->lnk_br;
+      freejktdbn (dbn);
+      dbn = next_dbn;
+#endif /* CONVERT_from_TOP */
+    }
+  return (cnt);
+}
+
+#ifdef  CONVERT_from_TOP
+static void
+sbn_set (dbn, pr_d_sbn, sone, sbn)
+     register struct JKT_DBN *dbn;
+     register struct DSD_SBN **pr_d_sbn;
+     register struct JKT_SONE *sone;
+     register struct JKT_SBN *sbn;
+{
+  int son, par;
+  register struct DSD_SBN *p_sbn;
+  if (sbn != 0)
+    {
+      sbn_set (dbn, pr_d_sbn, sone, sbn->parent);
+
+      son = cnt_son (dbn->sbn, sbn);
+      par = cnt_par (sbn);
+      p_sbn = *pr_d_sbn;
+      sons_set (dbn, sone, sbn, p_sbn, son, par);
+
+      (*pr_d_sbn)++;
+    }
+}
+
+static void
+sons_set (dbn, sone, sbn, p_sbn, son, par)
+     register struct JKT_DBN *dbn;
+     register struct JKT_SONE *sone;
+     register struct JKT_SBN *sbn;
+     register struct DSD_SBN *p_sbn;
+     register int son, par;
+{
+  register int i, j;
+
+  for (j = 0; j < son; j++)
+    {
+      for (sone = sbn->sbn; sone != 0; sone = sone->lnk_br)
+        {
+          for (i = 0; i < par; i++)
+            {
+              p_sbn->bun_m = sbn->bend_m;
+              p_sbn->bun_jc = sbn->j_c;
+              p_sbn->i_jc = sone->i_jc;
+              p_sbn->jentptr = sone->jentptr;
+              p_sbn->t_jc = sone->t_jc;
+              p_sbn->hinsi = sone->hinsi_fk;
+              p_sbn->kangovect = sbn->kangovect;
+              p_sbn->v_jc = sone->v_jc;
+              p_sbn->status_bkwd = sone->status_bkwd;
+              if (sbn->status == WNN_NOT_CONNECT && sone->jentptr == 0)
+                p_sbn->status = WNN_GIJI;
+              else
+                p_sbn->status = sbn->status;
+              p_sbn += dbn->sbn_cnt;
+            }
+        }
+    }
+}
+#endif /* CONVERT_from_TOP */
+
+/* 小文節の次候補の数 */
+int
+cnt_sone (sone)
+     register struct JKT_SONE *sone;
+{
+  register int i = 0;
+  while (sone)
+    {
+      i++;
+      sone = sone->lnk_br;
+    }
+  return (i);
+}
+
+/* その文節以後の総文節数 */
+static int
+cnt_par (sbn)
+     register struct JKT_SBN *sbn;
+{
+  register int cnt;
+  cnt = 1;
+  while (sbn->parent)
+    {
+      sbn = sbn->parent;
+      cnt *= cnt_sone (sbn->sbn);
+    }
+  return (cnt);
+}
+
+/* その文節以前の総文節数 */
+static int
+cnt_son (son, sbn)
+     register struct JKT_SBN *son;
+     register struct JKT_SBN *sbn;
+{
+  register int cnt;
+  cnt = 1;
+  while (son != sbn)
+    {
+      cnt *= cnt_sone (son->sbn);
+      son = son->parent;
+    }
+  return (cnt);
+}
+
+/* 1 大文節中の小文節の数 */
+static void
+cnt_sbn (sbn, d_cnt, s_cnt)
+     register struct JKT_SBN *sbn;
+     register int *d_cnt;
+     register int *s_cnt;
+{
+  *s_cnt = 0;
+  *d_cnt = 1;
+  while (sbn)
+    {
+      *d_cnt *= cnt_sone (sbn->sbn);
+      (*s_cnt)++;
+      sbn = sbn->parent;
+    }
+  *s_cnt *= *d_cnt;
+}
+
+/* 1 大文節の数 */
+static void
+cnt_dbn (dbn, dbn_cnt, sbn_cnt)
+     register struct JKT_DBN *dbn;
+     register int *dbn_cnt;
+     register int *sbn_cnt;
+{
+  int dbn_cnt_tmp;
+  int sbn_cnt_tmp;
+
+  *dbn_cnt = 0;
+  *sbn_cnt = 0;
+  while (dbn)
+    {
+      cnt_sbn (dbn->sbn, &dbn_cnt_tmp, &sbn_cnt_tmp);
+      *dbn_cnt += dbn_cnt_tmp;
+      *sbn_cnt += sbn_cnt_tmp;
+      dbn = dbn->lnk_br;
+    }
+}