#include <stdio.h>   /*   **************  bunp.c  ************** */
#include <string.h>  /* bunpo, atoc, betsuyaku, akitsume */
/* #include <process.h> */       /*    for MS-C && TURBO C++  */
/*      #include <stdlib.h>  preBunp, zokuCode, cjDisp ;  for Lattice C */
#include <ctype.h>  /* soreSorera, soreSjOj, sorera, soreCond, soreHuku */
		      /* sore, soreTan, soreSagashi, soreSaiyo, bsymbck */
#include "jehonfnc.h"   /* umekomi, umeTango, umeHsTango, umeError, bpoKisok */
		   /* henkei, narabeKae, seisei, sorecut, czConnec, czDel, bpoDbg */

#define  USER
/* #define  QWJTOE */

/* #define BIG_ENDIAN  Big Endian プロセッサー用 */
#define  BITS_32
/* #define  BITS_16  */

#include "macro.h"

static void atoc(void);
static void betsuyaku(int w, unsigned char hc);
static void preBunp(void);
static void zokuCode(int t, char cd);
static void cjDisp(void);
static int  bsymbck(int t, int aki);
static void umekomi(int ume);
static void umeTango(int ume, int t, char *pm, char qmk[]);
static void umeHsTango(unsigned char cd, int ume, int t, char *pju, char *pesh);
static void umeError(int ume);
static void bpoKisok(int ume);
static void henkei(void);
static void seisei(char cd, char sw);
static void narabeKae(void);
static int  quote_ck(char jj[], int t);
static int  akiTsume(char egq[], char md[], int egln);
static void czConnec(char cd);
static void zokuConn(int t, int lnt, char *ptmt, char *ptm1);
static void czDel(int t, char cd);
static int  czShorten(int t);
static void dumzShorten(char dumz[], char *dumz_8);
static void bpoDbg(void);
static void Draw_tree_main(char *dz[][], int pos[], char jnold[][], int iorig, int wnb2);
static int Def_wdcenter(FILE *tree_file, int iorig, int enlen[][], int jwdpt[], int ewdpt[], int wnb2, int i, int pos[], int k, int wdcenter[][], int wdtop[], int wdbottom[], int wnb3[]);
static void Draw_tree(FILE *tree_file, int iorig, int pos[], int wnb3[], int jwdpt[], int ewdpt[], int wdcenter[][], int wdtop[], int wdbottom[], char *dz[][], char jnold[][], int jnlen[], int enlen[][]);

#include "honyavar.h"


void bunpo(void) /* 文法規則により、訳語を結合するステップ */
begin
   register int t;
   int ume;

   atoc(); /* 訳語を変数 aj[][][] から、変数 cj[][] にコピーする。 */
   akitsume();
   preBunp(); /* 文法規則ステップのプレ処理 */
   cjDisp();   /* 文法ステップ訳語変数 cj[][], cz[][] の初期値表示 */
   csq[wnb + 1] = '\0';
   if (wnb < WordNumb - 1) {
   _  for (t = wnb + 1; t <= WordNumb - 1; t++) {
   _  _  cj[t][0] = '\0';     /* 余分な配列変数はゼロで埋めておく。*/
   _  _  cz[t][0] = '\0';
   _  }
   }
   ume = instrc(csq,'#');
   SERR = 0;
   if (ume == 0)
      ume = instrc(csq,'*');
   if (ume)
      umekomi(ume); /* まず埋め込み熟語のつくる句をすべて結合して、埋め込む。*/
   if (SERR == 0) {
   _  bpoKisok(0);
   _  for (t = 0; t <= WordNumb - 1; t++) {
   _  _  jwn[t][0] = '\0';
					  /* 次の翻訳に備えて和単語変数をゼロで初期化しておく。*/
   _  }
   }
end

static void atoc(void)
		  /* 訳語を変数 aj[][][] から、変数 cj[][] にコピーする。 */
begin     /* global variables: wnb, aj[][][], az[][][], cj[][], cz[][] */
   register int w, wc1;
   int  lnc;
   unsigned char hc = '\0', ajw0;

   for (w = 0; w <= wnb; w++) {
   _  ajw0 = aj[w][0][0];
   _  if ((w > 0) && (az[w - 1][0][0] == '#')) {
   _  _  hc = az[w - 1][0][2];
   _  _  if (hc && (! isdigit(hc)) && (hc != 'X'))
                                 /* 埋め込み型熟語 '#' の場合 */
   _  _     hc = '\0';           /* 以下で、品詞コード指定をチェックする。*/
   _  _  if ((! hc) || (hc == ajw0) || ((hc == '1' ) && ((ajw0 == '2') || ((ajw0 == '3') && strchr(az[w][0],'G')))) || ((w < wnb) && (az[w + 1][0][0] != '#'))) {
   _  _  _  strcpy(cj[w],aj[w][0]);
   _  _  _  strcpy(cz[w],az[w][0]);
   _  _  }
   _  _  else {
   _  _  _  if ( (hc == '6') && (ajw0 == '1') && (w < wnb) && (aj[w + 1][0][0] == '7') ) {
   _  _  _  _  strcpy(cj[w],aj[w][0]);  /* 副詞句が埋め込まれる場合。2002.10.27 */
   _  _  _  _  strcpy(cz[w],az[w][0]);
   _  _  _  }
   _  _  _  else {
   _  _  _  _  if (hc == aj[w][1][0]) {     /* 先頭の訳語候補が品詞指定に合致せず、*/
   _  _  _  _  _  for (wc1 = 1; wc1 <= YakMaxCt; wc1++) { /* ２番目の候補が合致する*/
   _  _  _  _  _  _  strcpy(aj[w][wc1 - 1],aj[w][wc1]);   /* 時は、後ろから詰める。*/
   _  _  _  _  _  _  strcpy(az[w][wc1 - 1],az[w][wc1]);
   _  _  _  _  _  _  if (! aj[w][wc1][0])
   _  _  _  _  _  _     break;
   _  _  _  _  _  }
   _  _  _  _  _  aj[w][YakMaxCt][0] = '\0';
   _  _  _  _  }
   _  _  _  }
   _  _  }
   _  }
   _  strcpy(cj[w],aj[w][0]);
   _  strcpy(cz[w],az[w][0]);
   _  if (aj[w][1][0])
   _     betsuyaku(w,hc); /* 別訳語の候補は全角括弧に入れて結合する。*/
   _  lnc = strlen(cj[w]);
   _  while (cj[w][lnc - 1] == ' ') {
   _  _  cj[w][lnc - 1] = '\0';
   _  _  lnc--;
   _  }
   }
end


static void betsuyaku(int w, unsigned char hc)
					 /* 別訳語の候補は全角括弧に入れて結合する。*/
begin     /* global variables: wnb, cj[][], aj[][][], az[][][] */
   register int wc1;
   int ln;
   char *pt;

   strcat(cj[w]," （");
   for (wc1 = 1; wc1 <= YakMaxCt; wc1++) {
   _  if (aj[w][wc1][0] == '\0')
   _     break;
   _  if (hc && (hc != aj[w][wc1][0]) && ((hc != '1') || (aj[w][wc1][0] != '2')) && ((w == wnb) || (az[w + 1][0][0] == '#')))
   _     break;
   _  if (strcmp(aj[w][0] + 1,aj[w][wc1] + 1)) {
   _  _  pt = cj[w];   /* 別訳語の候補は ',' で区切ってつなげておく。 */
   _  _  pt += strlen(pt);
   _  _  sprintf(pt,"%s, ",aj[w][wc1] + 1);
   _  }
   }
   ln = strlen(cj[w]) - 2;
   cj[w][ln] = '\0';
   if (ln > (JWordLen + 30)) {
   _  pt = strstr(cj[w],"（");
   _  if (pt)
   _     *pt = '\0';
   _  else
   _     cj[w][31] = '\0';
   _  strcat(cj[w],"（訳語を一部分切り捨てます。");
   }
   if (strstr(cj[w],"（")) /* 別訳語がある時は、括弧にいれておく。 */
	  strcat(cj[w],"）");
end

void akitsume(void)
	 /* 訳語変数 cj[] たちのうち、空白のものを後方番号のものから詰めて行く。*/
begin       /* global variables: wnb, ct, cj[][]  */
   register int i, j;
   int cnt, aki = 0;

   for (i = 0; i <= wnb; i++) {
   _  if (! cj[i][0]) {
   _  _  aki = 1;
   _  _  break;
   _  }
   }
   if (aki) {
   _  cnt = i - 1;
   _  if (i == wnb)
   _     wnb--;
   _  else {
   _  _  for (j = i + 1; j <= wnb; j++) {
   _  _  _  if (cj[j][0]) {
   _  _  _  _  cnt++;
   _  _  _  _  strcpy(cj[cnt],cj[j]);
   _  _  _  _  strcpy(cz[cnt],cz[j]);
   _  _  _  _  strcpy(jwn[cnt],jwn[j]);
   _  _  _  _  strcpy(jwn0[cnt],jwn0[j]);
   _  _  _  }
   _  _  }
   _  _  wnb = cnt;
   _  _  cj[wnb + 1][0] = '\0';
   _  }
   }
end

static void preBunp(void) /* 文法規則ステップのプレ処理 */
begin  /* global variables: wc, wnb, cj[][], cz[][], en[] */
   register int t;
   int aki = 0;
   char cd, *ptc, *ptq;

   wc = 0;
   for (t = 0; t <= wnb; t++) {
   _  cd = cj[t][0];
   _  zokuCode(t,cd); /* 必要な属性コードの付加、不用なコードの削除 */
   _  if (cd == '3' || cd == '4') {
   _  _  ptc = strchr(cz[t],'p');
   _  _  if (! ptc)
   _  _     ptc = strchr(cz[t],'P');
   _  _  if (ptc && (strlen(cj[t]) >= 2) && strchr(ptc + 1,'|'))
   _  _     past(cj[t] + 1,t,1);   /* 英語訳語の過去形を作る。*/
   _  _  else {
   _  _  _  ptq = strchr(cz[t],'G');
   _  _  _  if (ptq && (! strstr(ptq,"状")))
   _  _  _    if (strchr(ptq,'|')) /*ここは１つ上の行とまとめられない。*/
   _  _  _        sinko(cj[t]);     /* TURBO C/C++ のバグらしい。*/
   _  _  }
   _  }
   _  aki = bsymbck(t,aki);
   }                     /* 左隣１語 '<', 右隣１語 '$', コメント '*' の処理 */
   if (aki == 1)
	  akitsume();
end

static void zokuCode(int t, char cd) /* 必要な属性コードの付加、不用なコードの削除 */
begin  /* global variables: cj[][], cz[][], en[][] */
   unsigned int *pti, code;
   char *ptr, *ptc, *pt2;

   ptr = strchr(cz[t],'r');
   if (ptr && strchr(ptr + 1,'|')) { /* 関係代名詞（副詞）の先行詞に属性マーク '&' */
   _  if (t && (cj[t - 1][0] == '1')) {                    /* を付加する。*/
   _  _  if (strcmp(jwn[t],"when") || strchr(cz[t - 1],'t'))
   _  _     ptinsert(cz[t - 1],"&");
   _  }
   _  else {
   _  _  if ((t >= 2) && (cj[t - 1][0] == '7') && (cj[t - 2][0] == '1'))
   _  _     ptinsert(cz[t - 2],"&");        /* "in which" などの場合 */
   _  }
   }
   if ((cj[t][0] == '2') && t && (cj[t - 1][0] == '1') && (cj[t + 1][0] == '3')) {               /* 関係代名詞の先行詞に属性マーク '&' を付加する。*/
   _  if (((t > 2) && (cz[t - 2][0] == 'd') && (cj[t - 3][0] == '3')) || ((t > 3) && (cz[t - 3][0] == 'd') && (cj[t - 4][0] == '3')))
   _    ptinsert(cz[t - 1],"&");
   }
   if (cd != '3' && cd != '4' && cd != '5') {
   _  pt2 = strchr(cz[t],'|');
   _  ptc = strchr(cz[t],'G');
   _  if (! ptc)
   _     ptc = strchr(cz[t],'P');
   _  while (ptc && (ptc < pt2)) {
   _  _  pti = (unsigned int *)jis2sjis(euc2jis((unsigned char *)(ptc - 1)));
#if defined(BIG_ENDIAN)
   _  _  code = *pti >> 20;
#endif
#if defined(BITS_32)
   _  _  code = (*pti << 24) >> 24;
#endif
#if defined(BITS_16)
   _  _  code = (*pti << 8) >> 8;
#endif
   _  _  if ((ptc == cz[t]) || (code < 0x81))
   _  _     ptcut(ptc,1);
   _  _  else
   _  _     break;
   _  _  ptc = strchr(cz[t],'G');
   _  _  if (! ptc)
   _  _     ptc = strchr(cz[t],'P');
   _  }
   }
   if (! strchr("13456X",cd)) {
   _  pt2 = strchr(cz[t],'|');
   _  if (pt2) {
   _  _  ptc = strchr(cz[t],'p');
   _  _  while (ptc) {
   _  _  _  if (ptc < pt2) {
   _  _  _  _  if ( (cd != '1') || (! strchr(cz[t],'t')) || (strchr(cz[t],'t') > pt2) ) {
   _  _  _  _  _  ptcut(ptc,1);  /* 名詞では属性に't'と'p'が有れば両方残す。2005.06.27 */
   _  _  _  _  _  --pt2;
   _  _  _  _  }
   _  _  _  _  else
   _  _  _  _     ++ptc;
   _  _  _  _  ptc = strchr(ptc,'p');
   _  _  _  }
   _  _  _  else
   _  _  _     break;
   _  _  }
   _  }
   }
end


static void cjDisp(void) /* 文法ステップ訳語変数 cj[][], cz[][] の初期値表示 */
begin   /* global variables: Dbg, Dbg2, wnb, cj[][], cz[][], csq[], sj[], sz[], oj[], oz[], vr[], vz[], sj2[], oj2[], vr2[] */
   register int t;
   int ln;

   if (Dbg == 'Y' || Dbg == 'y') {
   _  printf("\n\n");
   _  printf("sj = %s  sz = %s  oj = %s  oz = %s  vr = %s  vz = %s \n",sj,sz,oj,oz,vr,vz);
   _  printf(" sj2 = %s, oj2 = %s, vr2 = %s  \n",sj2,oj2,vr2);
   _  printf("   washa = %s, washa2 = %s, washa3 = %s \n",washa,washa2,washa3);
   }
#if defined(USER)
   _  if (Dbg2 == 'Y') {
   _  _  fprintf(dbgfl_pt,"\n\n");
   _  _  fprintf(dbgfl_pt,"sj = %s  sz = %s  oj = %s  oz = %s  vr = %s  vz = %s \n",sj,sz,oj,oz,vr,vz);
   _  _  fprintf(dbgfl_pt,"  sj2 = %s, sz2 = %s, oj2 = %s, oz2 = %s, vr2 = %s, vz2 = %s \n",sj2,sz2,oj2,oz2,vr2,vz2);
   _  _  fprintf(dbgfl_pt,"    washa = %s, washa2 = %s, washa3 = %s \n",washa,washa2,washa3);
   _  }
#endif
   for (t = 0; t <= wnb; t++)
	  csq[t] = cj[t][0];
  if (Dbg == 'Y' || Dbg == 'y') {
   _  for (t = 0; t <= wnb; t++) {
   _  _  ln = strlen(cj[t]);
   _  _  color_white;
   _  _  printf("\n jwn[%d] = %s \n",t,jwn[t]);
   _  _  if (ln < 14) {
   _  _  _  printf("cj[%d] = ",t);
   _  _  _  color_magenta;
   _  _  _  printf("%c",cj[t][0]);
   _  _  _  color_light_blue;
   _  _  _  printf("%-14s",cj[t] + 1);
   _  _  }
   _  _  else {
   _  _  _  if (ln < 24) {
   _  _  _  _  printf("cj[%d] = ",t);
   _  _  _  _  color_magenta;
   _  _  _  _  printf("%c",cj[t][0]);
   _  _  _  _  color_light_blue;
   _  _  _  _  printf("%-24s",cj[t] + 1);
   _  _  _  }
   _  _  _  else {
   _  _  _  _  printf("cj[%d] = ",t);
   _  _  _  _  color_magenta;
   _  _  _  _  printf("%c",cj[t][0]);
   _  _  _  _  color_light_blue;
   _  _  _  _  printf("%s\n",cj[t] + 1);
   _  _  _  _  printf("%-23s","   ");
   _  _  _  }
   _  _  }
   _  _  color_green;
   _  _  printf("cz[%d] = %s  \n",t,cz[t]);
#if defined(USER)
   _  _  if (Dbg2 == 'Y') {
   _  _  _  if (ln < 14)
   _  _  _     fprintf(dbgfl_pt,"cj[%d] = %-15s",t,cj[t]);
   _  _  _  else {
   _  _  _  _  if (ln < 24)
   _  _  _  _     fprintf(dbgfl_pt,"cj[%d] = %-25s",t,cj[t]);
   _  _  _  _  else {
   _  _  _  _  _  fprintf(dbgfl_pt,"cj[%d] = %s\n",t,cj[t]);
   _  _  _  _  _  fprintf(dbgfl_pt,"%-23s","   ");
   _  _  _  _  }
   _  _  _  }
   _  _  _  fprintf(dbgfl_pt,"cz[%d] = %s  \n",t,cz[t]);
   _  _  }
#endif
   _  _  color_white;
   _  _  pause(2000);
   _  }
   }
end


static int  bsymbck(int t, int aki)
				  /* 左隣１語 '<', 右隣１語 '$', コメント '*' の処理 */
begin             /* global variables: cj[][], cz[][], jwn[][] */
   char *ptj, *dums, *ptp, *ptvl;

   ptj = strchr(cj[t],'<');
   if (ptj) {  /* 左隣りの１語を取り込む。*/
   _  ptreplace(ptj,1,cj[t - 1] + 1);
   _  cj[t - 1][0] = '\0';
   _  ptvl = strchr(cz[t - 1],'|');
   _  ptp = strchr(cz[t],'|');
   _  if (ptvl && ptp) {
   _  _  strcat(cz[t],ptvl + 1);
   _  _  *(ptvl) = '\0';
   _  _  ptinsert(ptp,cz[t - 1]);
   _  }
   _  else
   _     strcat(cz[t],cz[t - 1]);
   _  strcat(jwn[t - 1]," ");
   _  strcat(jwn[t - 1],jwn[t]);
   _  strcpy(jwn[t],jwn[t - 1]);
   _  jwn[t - 1][0] = '\0';
   _  aki = 1;
   }
   if (strchr(cj[t],'*')) {  /* コメントのナンバーを訳語にも附加する。*/
   _  dums = cz[t] + 1;
   _  strcat(cj[t],dums);
   }
   ptj = strchr(cj[t],'$');
   if (ptj) { /* 右隣りの１語を取り込む。*/
   _  ptp = strstr(cj[t],"（");
   _  if ((! ptp) || (ptp > ptj)) {
   _  _  ptcut(cj[t + 1],1);         /* cj[t + 1] の品詞コードを削除した。*/
   _  _  if (strstr(cj[t],"今") && strstr(cj[t + 1],"曜日") && ((cj[t] + 3) == ptj)) {
   _  _  _  ptreplace(ptj,1,"週の");
   _  _  _  strcat(cj[t],cj[t + 1]);  /* cj[t + 1] の品詞コードは既に無い。 */
   _  _  }
   _  _  else
   _  _     ptreplace(ptj,1,cj[t + 1]);
   _  _  cj[t + 1][0] = '\0';
   _  _  strcat(cz[t],cz[t + 1]);
   _  _  strcat(jwn[t]," ");
   _  _  strcat(jwn[t],jwn[t + 1]);
   _  _  aki = 1;
   _  }
   }
   return(aki);
end

static void umekomi(int ume)
         /* まず埋め込み熟語のつくる句をすべて結合して、埋め込む。 */
begin    /* global variables: csq[],cj[][],cz[][],jwn[][],wc,md[][],oj[],oz[] */
   register int t;
   int  ume1, nxtUme;
   unsigned int ln;
   char qmk[3], *pm;

   ume1 = ume + 1;
   while (ume > 0) {
   _  if (csq[ume] == '#' || csq[ume1] == '#' || csq[ume1] == '*' || csq[ume1] == '\0' || csq[ume] == '\0') {
   _  _  if ((strcmp(jwn[ume],"妻") == 0) && (! strstr(jps,"私")))
   _  _     ptinsert(cj[ume] + 1,"his ");
   _  _  else {
   _  _  _  if (strcmp(jwn[ume],"両親") == 0)
   _  _  _     ptinsert(cj[ume] + 1,"my ");
   _  _  _  else {
   _  _  _  _  if (! strchr(cj[ume],' ')) {
   _  _  _  _  _  if (strchr(cz[ume],'d') || strstr(cz[ume],"y箇所"))
   _  _  _  _  _     ptinsert(cj[ume] + 1,"the ");
   _  _  _  _  _  else {
   _  _  _  _  _  _  if (strchr(cz[ume],'y') && (! strchr(cz[ume],'X')) && (! strstr(cz[ume],"複"))) {
   _  _  _  _  _  _  _  if (isVowel(cj[ume][1]))
   _  _  _  _  _  _  _     ptinsert(cj[ume] + 1,"an "); /* 不定冠詞を付ける場合  2001.02.27 追加 */
   _  _  _  _  _  _  _  else
   _  _  _  _  _  _  _     ptinsert(cj[ume] + 1,"a ");
   _  _  _  _  _  _  }
   _  _  _  _  _  }
   _  _  _  _  }
   _  _  _  }
   _  _  }
   _  _  left(qmk,cz[ume - 1],2);
   _  _  if (*qmk == '*')
   _  _     *qmk = '%';
   _  _  nxtUme = 0;
   _  _  for (t = ume - 2; t >= 0; t--) {
   _  _  _  pm = strstr(cj[t],qmk);
   _  _  _  if (pm) {  /* 埋め込み先を探す。 */
   _  _  _  _  if (csq[ume] != '#') /* 埋め込み先の熟語に単語を置き戻す。*/
   _  _  _  _     umeTango(ume,t,pm,qmk);
   _  _  _  _  else {
   _  _  _  _  _  ptcut(pm,2);
   _  _  _  _  _  ptcut(csq + ume - 1,1);
   _  _  _  _  }
   _  _  _  _  if (SERR != 5) {/* 埋め込み型熟語の結合に失敗すると SERR == 5 */
   _  _  _  _  _  cj[ume - 1][0] = '\0';
   _  _  _  _  _  akitsume();
   _  _  _  _  _  nxtUme = 1;
   _  _  _  _  }
   _  _  _  _  break;
   _  _  _  }
   _  _  }
   _  _  if ((SERR != 5) && (! nxtUme)) {
   _  _  _  cj[ume - 1][0] = '\0';
   _  _  _  cj[ume][0] = '\0';
   _  _  _  akitsume();
   _  _  _  ptcut(csq + ume - 1,2);
   _  _  }
   _  }
   _  else {
   _  _  ln = strlen(csq);
   _  _  bpoKisok(ume);
   _  _  if (ln == strlen(csq)) {
   _  _  _  SERR = 5;
   _  _  }
   _  }
   _  if (SERR == 5) {
   _  _  umeError(ume); /* 誤って埋め込み型熟語を採用した時のバックトラック */
   _  _  break;
   _  }
   _  else {
   _  _  ume = instrc(csq,'#');
   _  _  if (ume == 0)
   _  _     ume = instrc(csq,'*');
   _  _  ume1 = ume + 1;
   _  }
   }
end

static void umeTango(int ume, int t, char *pm, char qmk[])
begin                            /* 埋め込み先の熟語に単語を置き戻す。*/
   int flg, jm; /* global var: wc, SERR, jwn[][], md[][], oj[], oz[] */
   char *pju, *pesh, umw[JSentLen], kaku[3], *ptm1, *ptmu, *ptpa, *ptsh;
   unsigned char cd;

   if (cj[ume][0])
      strcpy(umw,cj[ume] + 1);
   else
      *umw = '\0';
   pju = strchr(cj[t],'#');
   if (pju) {
   _  cd = (unsigned char) *(pju + 2);
   _  flg = 8;
   _  if ((! isdigit(cd)) && (cd != 'p') && (cd != 'h'))
   _     flg = 0;
   _  ptm1 = strchr(cz[t],'|');
   _  if (ptm1 && (*umw == 'a') && ((*(umw + 1) == ' ') || ((*(umw + 1) == 'n') && (*(umw + 2) == ' ')))) {
   _  _  ptpa = strchr(ptm1 + 1,'(');
   _  _  if (ptpa) {
   _  _  _  ptsh = strchr(ptpa + 1,'#');
   _  _  _  if (ptsh && ((*(ptsh - 1) == '5') || (*(ptsh - 1) == '8'))) {
   _  _  _  _  if (*(umw + 1) == ' ')
   _  _  _  _     ptcut(umw,2); /* 余分な不定冠詞のダブリを削除する。*/
   _  _  _  _  else             /* 2001.03.13 追加した。*/
   _  _  _  _     ptcut(umw,3);
   _  _  _  }
   _  _  }
   _  }
   _  pesh = strchr(jwn[t],'#');
   _  if (flg)     /* 埋め込み型熟語の品詞指定が有る場合 */
   _     umeHsTango(cd,ume,t,pju,pesh);
   _  else {
   _  _  if ((! cj[ume][0]) && (strchr(cz[t],'P') || strchr(cz[t],'p')) && (strcmp(jwn[t - 1],"be") == 0)) {
   _  _  _  ptcpy(kaku,pju + 2,pju + 4);
   _  _  _  if ((strcmp(kaku,"を") == 0) || (strcmp(kaku,"に") == 0) || (strcmp(kaku,"と") == 0)) {
   _  _  _  _  ptcut(pju,4);
   _  _  _  }
   _  _  _  else
   _  _  _     ptcut(pju,2);
   _  _  }
   _  _  else
   _  _     ptreplace(pm,2,umw);
   _  _  if (*(pesh + 1) == ' ')
   _  _     ptreplace(pesh,1,jwn[ume]);
   _  _  else   /* 日本語単語の中の'#'も、元の日本語単語に置き戻しておく */
   _  _     ptreplace(pesh,2,jwn[ume]);
   _  }
   }
   else
      if (*qmk == '%' && *umw) {
      _  ptinsert(umw,"（");
      _  strcat(umw,"）");
      _  ptreplace(pm,2,umw);
      }
   if (SERR != 5) {
   _  ptm1 = strchr(cz[t],'|');
   _  ptmu = strchr(cz[ume],'|');
   _  if (ptmu && *(ptmu + 1))
   _     strcat(cz[t],ptmu + 1);
   _  *ptmu = '\0';
   _  if (ptm1)
   _     ptinsert(ptm1,cz[ume]);
   _  else
   _     strcat(cz[t],cz[ume]);
   _  if (cj[ume][0] == '1' && cj[t][0] == '3') {
   _  _  wc = t;
   _  _  jm = ume - t;
   _  _  if (jm < 8) {
   _  _  _  strcpy(md[jm],cj[ume]);
 /*  _  _  _  sopresv(oj,oz,jm);   */
   _  _  }
   _  }
   _  if (pm == cj[t])
   _     ptinsert(cj[t],"6");
   _  cj[ume][0] = '\0';
   _  ptcut(csq + ume - 1,2);
   }
end

static void umeHsTango(unsigned char cd, int ume, int t, char *pju, char *pesh)        /* 埋め込み型熟語の品詞指定が有る場合 */
begin            /* global var:  SERR, cj[][], cz[][], jwn[][]  */
   char kaku[3], ume_char[2], cj_umeq[SentLen];

   if ((cd == cj[ume][0]) || (cd == '1' && cj[ume][0] == '2') || (cd == 'p' && cj[ume][0] == '8') || (cd == 'h' && cj[ume][0] == '2')) {
   _  if (cj[ume][0] == '1') {
   _  _  strcpy(cj_umeq,cj[ume] + 1);
   _  _  ume_char[0] = '0';
   _  _  ume_char[1] = '\0';
   _  _  kanshi(cj_umeq,ume,ume_char);
   _     ptreplace(pju,3,cj_umeq);
   _  }
   _  else
   _     ptreplace(pju,3,cj[ume] + 1);
   _  if (*(pesh + 1) == ' ')
   _     ptreplace(pesh,1,jwn[ume]);
   _  else
   _     ptreplace(pesh,2,jwn[ume]);
   }       /* 日本語単語の中の'#'も、元の日本語単語に置き戻しておく */
   else {
   _  if ((cd == '1') && (cj[ume][0] == '3') && strchr(cz[ume],'G')) {
   _  _  strcat(cj[ume],"事");
   _  _  cz[ume][0] = '\0';
   _  _  ptreplace(pju,3,cj[ume] + 1);
   _  _  if (*(pesh + 1) == ' ')
   _  _     ptreplace(pesh,1,jwn[ume]);
   _  _  else
   _  _     ptreplace(pesh,2,jwn[ume]);
   _  }
   _  else {
   _  _  if ((! cj[ume][0]) && (cd == '1') && (strchr(cz[t],'P') || strchr(cz[t],'p')) && (strcmp(jwn[t - 1],"be") == 0)) {
   _  _  _  ptcpy(kaku,pju + 3,pju + 5);
   _  _  _  if ((strcmp(kaku,"を") == 0) || (strcmp(kaku,"に") == 0) || (strcmp(kaku,"と") == 0)) {
   _  _  _  _  ptcut(pju,5);
   _  _  _  }
   _  _  _  else
   _  _  _     ptcut(pju,3);
   _  _  _  ptcut(pesh,2);
   _  _  }
   _  _  else {
   _  _  _  if ( (cd == '5') && (cj[ume][0] == '1') && (strcmp(cz[ume],"n|全") == 0) ) {
   _  _  _  _  ptreplace(pju,3,cj[ume] + 1); /* 形容詞指定で埋め込み単語が数詞名詞の場合。2004.06.13 追加 */
   _  _  _  _  ptreplace(pesh,2,jwn[ume]); /* 日本語単語の中の'#'も、元の日本語単語に置き戻しておく */
   _  _  _  }
   _  _  _  else
   _  _     SERR = 5;
   _  _  }
   _  }
   }
end

static void umeError(int ume) /* 誤って埋め込み型熟語を採用した時のバックトラック */
begin     /* global variables: SERR, SERRNB, csq[], cj[][], cz[][], jwn[][] */
   register int t;
   int umct;
   char qmk[3];

   printf("\n\n  # エラー。csq = %s  \n\n\n",csq);
   left(qmk,cz[ume - 1],2);
   umct = 0;
   for (t = ume - 2; t >= 0; t--) {
   _  if (strstr(cj[t],qmk)) {
   _  _  printf("# の熟語 = %s, %s \n",jwn[t],cj[t]);
   _  _  umct = 1;
   _  _  SERRNB = t;
   _  _  break;
   _  }
   }
   if (! umct) {
   _  for (t = ume - 2; t >= 0; t--) {
   _  _  if (((cz[t][0] == 'R') || strchr(jwn[t],'#')) && (! strchr(cj[t],'#'))) {
   _  _  _  printf("# の熟語 = %s, %s \n",jwn[t],cj[t]);
   _  _  _  umct = 1;
   _  _  _  break;
   _  _  }
   _  }
   }
   printf("誤って # の熟語を採用したので、バックトラックして、辞書引きをやり直します。 \n");
   for (t = 0; t <= ume; t++)
      printf("\n jwn[%d] = %s,   cj[%d] = %s \n",t,jwn[t],t,cj[t]);
   pause(15000);
end


static void bpoKisok(int ume)  /* 文法規則を適用して句を生成するプロセス */
begin             /* global variables: DRV,lnb,wnb,wc,te,pbun[],csq[],dumb[] */
   int t, ln;
   int j, k = 0, iorig = 0, wnb2, pos[100];   /*  2004.11.9 追加 */
   char tf, sw, *pt2, *pth, *cdp;
   char bsq[10], Bunpofile[15], pbunq[200];
   char *dj1[100][100],*dj2[100][100],djold[20][WordNumb][SentLen], jnold[100][100];       /*  2004.11.9 追加 */
   FILE *bunpt;
#if defined(USER)
   char bunpnb[5];
#endif


/*   Bunpofile[0] = DRV;
   Bunpofile[1] = '\0';
   strcat(Bunpofile,":bunpo.jte");   UNIXでは使わない  */

   strcpy(Bunpofile,"bunpo.jte");   /* UNIX用 */

   if ((bunpt = fopen(Bunpofile,"r")) == NULL) {
   _  printf("Bunpofile がオープンできませんでした。");
   _  exit(1);
   }
   /* 2004.11.9 追加 */
   /* 英単語cj[t][1]をdj2[t][iorig]に格納 */
   /* 文法規則を適用する単語列の先頭と末尾の単語番号であるwcとteをpos[]に */
   /* 順次格納していく */
   if(TREE == 'Y') {
   /* 日本語単語数と日本語単語の保持 */
   _  for(j = 0; j <= wnb; j++)
   _  wnb2 = wnb;
   _    strcpy(jnold[j], jwn[j]);
   _  strcpy(jnold[j], "\0");
   /* 英単語の保持 */
   _  for(j = 0; j <= wnb; j++) {
   _  _  dj1[0][j] = cj[j]+1;
   _  _  strcpy(djold[0][j], dj1[0][j]);
   _  _  dj2[0][j] = djold[0][j];
   _  }
   _  strcpy(djold[0][j], "\0");
   _  dj2[0][j] = djold[0][j];
   }
   *pbun = '\0';
   while (fgets(pbunq,198,bunpt)) {
   _  if (! strstr(pbunq,"***")) {
   _  _  ln = strlen(pbunq);
   _  _  if (ln > 182) {
   _  _  _  printf("\n 文法規則が長過ぎます。pbun = %s \n",pbunq);
   _  _  _  printf("\n 長さ = %d  これを 182 文字以内に削ってください。\n",ln);
   _  _  _  exit(1);
   _  _  }
   _  _  else
   _  _     strcpy(pbun,pbunq);
   _  _  pt2 = csq + ume;
   _  _  strcpy(dumb,pbun + 2);
   _  _  cdp = strchr(dumb,';');
   _  _  if (cdp > dumb + 8) {
   _  _  _  printf("\n 文法規則が９語以上に関係しています。\n");
   _  _  _  printf("pbun = %s \n",pbun);
   _  _  _  printf("\n unexpected error might occur !! \n\n");
   _  _  _  printf("文法規則を修正してください。\n");
   _  _  _  exit(1);
   _  _  }
   _  _  ptcpy(bsq,dumb,cdp);
#if defined(USER)
   _  _  if (*BPWATCH) {
   _  _  _  ln = strlen(dumb);
   _  _  _  ptcpy(bunpnb,dumb + ln - 6,dumb + ln - 2);
   _  _  _  if ((strcmp(bunpnb,BPWATCH) == 0) && (! strstr(pt2,bsq))) {
   _  _  _  _  beeping(10);
   _  _  _  _  printf("\n 注目している文法規則 %s に当てはまる品詞コード列が存在しません！！ \n",pbun);
   _  _  _  _  printf("     現在の品詞コード列は %s です。\n",pt2);
   _  _  _  }
   _  _  }
#endif
   _  _  pth = strstr(pt2,bsq);
   _  _  while (pth) {
   _  _  _  wc = wnb + 1 - strlen(pth);
   _  _  _  lnb = strlen(bsq) - 1;
   _  _  _  te = wc + lnb;
   /* ******************** DBG ****************** */
   _  _  _  if (strstr(pbun,"; Q8"))
               printf(" ");
   /* ******************** DBG ****************** */
   _  _  _  tf = bunpcd();    /* 文法規則の適用条件の合否の判定 */
   _  _  _  if (tf == 'T') {  /* tf == 'T' なら合格、tf == 'F' なら失格 */
      /*****  文法規則の適用（英訳語の人称、時制の活用など） **********/
   _  _  _  _  henkei();               /* 文法規則により、文字列を変形する */

   /* 2004.11.9 追加 */
   /* 英単語cj[t][1]をdj2[t][iorig]に格納 */
   /* 文法規則を適用する単語列の先頭と末尾の単語番号であるwcとteをpos[]に */
   /* 順次格納していく */
   _  _  _  _  if(TREE == 'Y') {
   /* 日本語単語数と日本語単語の保持 */
   _  _  _  _  _  if(iorig == 0) {
   _  _  _  _  _  _  wnb2 = wnb;
   _  _  _  _  _  _  for(j = 0; j <= wnb2; j++)
   _  _  _  _  _  _    strcpy(jnold[j], jwn[j]);
   _  _  _  _  _  _  strcpy(jnold[j], "\0");
   _  _  _  _  _  }
   /* 英単語の保持 */
   _  _  _  _  _  for(j = 0; j <= wnb2; j++) {
   _  _  _  _  _  _  dj1[iorig][j] = cj[j]+1;
   _  _  _  _  _  _  strcpy(djold[iorig][j], dj1[iorig][j]);
   _  _  _  _  _  _  dj2[iorig][j] = djold[iorig][j];
   _  _  _  _  _  }
   _  _  _  _  _  strcpy(djold[iorig][j], "\0");
   _  _  _  _  _  dj2[iorig][j] = djold[iorig][j];
   _  _  _  _  _  iorig ++;
   /* 文法規則適用範囲の格納 */
   _  _  _  _  _  pos[k] = wc;
   _  _  _  _  _  pos[k + 1] = te;
   _  _  _  _  _  k += 2;
   _  _  _  _  }

   _  _  _  _  sw = *(cdp + 3);
   _  _  _  _  narabeKae();            /*  訳語の語順を並べ換える。 */
   _  _  _  _  seisei(*(cdp + 1),sw);  /*  単語を結合して、句を生成する。 */
   _  _  _  _  if (*(bsq + 1)) {
   _  _  _  _  _  czConnec(*(cdp + 1)); /* 属性変数を結合する。 */
   _  _  _  _  _  akitsume();
   _  _  _  _  }
   _  _  _  _  if (Dbg == 'Y' || Dbg == 'y')
   _  _  _  _     bpoDbg();  /* 文法規則とその適用結果を画面に表示する。*/
   _  _  _  _  for (t = 0; t <= wnb; t++)
   _  _  _  _     csq[t] = cj[t][0];
   _  _  _  _  csq[wnb + 1] = '\0';
   _  _  _  }
   _  _  _  if (tf == 'T' && *(bsq + 1))
   _  _  _     pt2 = pth;
   _  _  _  else
   _  _  _     pt2 = pth + 1;
   _  _  _  strcpy(dumb,pbun + 2);
   _  _  _  pth = strstr(pt2,bsq);
   _  _  }
   _  }
   }
      /* *********************** DBG *********************** */
   if(TREE == 'Y')
      printf("\n Going to Draw_tree_main(); iorig = %d, wnb2 = %d,",iorig,wnb2);
      /* *********************** DBG *********************** */
   if(TREE == 'Y')
      Draw_tree_main(dj2, pos, jnold, iorig, wnb2);  /* 単語結合の過程を図示する関数 */
   fclose(bunpt);
end

static void henkei(void)  /* 文法規則により、文字列を変形する */
      /* global variables: wc, lnb, md[][], cj[][][] */
begin
   register int t;
   char   *pt;

   for (t = 0; t <= 7; t++) {
   _   strcpy(md[t],cj[wc + t]);
   }
   pt = strchr(dumb,'#');
   while (pt) {
   _  if (*(pt + 1) != ';')  /* 埋め込み記号との混同を回避する。 2001.03.13 */
   _     transf(pt);         /* 文法規則のコマンドを下請け関数に実行させる。*/
   _  *pt = ' ';
   _  pt = strchr(dumb,'#');
   }
   if (lnb < 7) {
   _  for (t = lnb + 1; t <= 7; t++) {
   _  _  if ((md[t][0] == 'Z') && isdigit(md[t][1]))
   _  _     strcpy(cj[wc + t],md[t] + 1);
   _  _  else {
   _  _  _  if ((md[t][0] == cj[wc + t][0]) && (strcmp(md[t] + 1,"Z") == 0))
   _  _  _     cj[wc + t][1] = '\0';
   _  _  _  else
   _  _  _     strcpy(cj[wc + t],md[t]);
   _  _  }
   _  _  md[t][0] = '\0';
   _  }
   }
end

static void seisei(char cd, char sw)    /* 単語を結合して、句を生成する。 */
begin        /* global variables: dumb[], md[][], cj[][], cz[][], wc, lnb */
   register int t;
   int egln;
   char *ptc, *ptz, *ptp1, *ptp2, *pt_bar, egq[256], czq[5];
   char jpq[JSentLen], jp0q[JSentLen];

   if (cj[wc][0] == '7') {
   _  *czq = '\0'; /* 前置詞('7')の属性は、'O'と's' 以外は消去する。*/
   _  if (strchr(cz[wc],'O'))
   _     strcpy(czq,"O");
   _  if (strchr(cz[wc],'s'))
   _     strcat(czq,"s");
   _  pt_bar = strchr(cz[wc],'|');
   _  if (pt_bar)         /* 第2属性は残すことにした。2002.08.22 */
   _     strcat(czq,pt_bar);
   _  strcpy(cz[wc],czq);
   }
   egq[0] = cd;
   egq[1] = '\0';
   *jpq = '\0';
   *jp0q = '\0';
   egln = 1;
   if (sw == '0') {           /* 訳語を正順に結合する。 */
      for (t = 0; t <= lnb; t++) {
      _  egln += strlen(md[t]);
      _  if (egln >= SentLen) {
      _  _  egln = akiTsume(egq,md[t],egln);
      _  _  if (egln >= SentLen) {
      _  _  _  if (strlen(egq) > (SentLen - 38)) {
      _  _  _  _  sprintf(egq + SentLen - 38,".... 翻訳文が長くなり過ぎます！ ");
      _  _  _  _  break;
      _  _  _  }
      _  _  _  else
      _  _  _     sprintf(md[t] + SentLen - 40 - strlen(egq),".... 翻訳文が長くなり過ぎます！ ");
      _  _  }
      _  }
      _  if (md[t][1] == 'Z') {
      _  _  if (md[t][2])
      _  _     ptcut(md[t] + 1,1);
      _  _  else {
      _  _  _  if (lnb)
      _  _  _     md[t][0] = '\0';
      _  _  _  else
      _  _  _     md[t][1] = '\0';
      _  _  }
      _  }
      _  if (md[t][0]) {
      _  _  if (t && (md[t][0] == 'X') && md[t - 1][0] && md[t - 1][1] && strstr("0.??0!",md[t - 1]))
      _  _     md[t][1] = toupper(md[t][1]);
      _  _  ptc = strchr(md[t],'/');
      _  _  if ( ptc && *(egq + 1) && strcmp(ptc - 2,"c / o") ) {
      _  _  _  ptp1 = strstr(md[t],"（");  /* 上の第３の条件を加えた。2002.10.16 */
      _  _  _  if (ptp1)
      _  _  _     ptp2 = strstr(ptp1 + 2,"）");
      _  _  _  if (ptp1 && ptp2 && (ptp1 < ptc) && (ptc < ptp2))
      _  _  _     strcat(egq,md[t]);
      _  _  _  else {
      _  _  _  _  strcat(egq,ptc + 1);
      _  _  _  _  *ptc = '\0';                    /* 分離型訳語の結合 */
      _  _  _  _  ptinsert(egq + 1,md[t] + 1);
      _  _  _  _  ptz = strchr(cz[wc + t],'/');
      _  _  _  _  if (ptz)
      _  _  _  _     *ptz = *egq;
      _  _  _  }
      _  _  }
      _  _  else {
      _  _  _  if (md[t][1] == '@')
      _  _  _     ptcut(md[t] + 1,1);
      _  _  _  else {
      _  _  _  _  if (*(egq + 1) && quote_ck(egq,t))
      _  _  _  _     strcat(egq," ");
      _  _  _  }
      _  _  _  strcat(egq,md[t] + 1);
      _  _  }
      _  }
      _  strcat(jpq,jwn[wc + t]);
      _  jwn[wc + t][0] = '\0';
      _  strcat(jp0q,jwn0[wc + t]);
      _  jwn0[wc + t][0] = '\0';
      }
   }
   else {                       /* 訳語を逆順に結合する。 */
      for (t = 0; t <= lnb; t++) {
      _  egln += strlen(md[lnb - t]);
      _  if (egln >= SentLen) {
      _  _  egln = akiTsume(egq,md[lnb - t],egln);
      _  _  if (egln >= SentLen) {
      _  _  _  if (strlen(egq) > (SentLen - 38)) {
      _  _  _  _  sprintf(egq + SentLen - 38,".... 翻訳文が長くなり過ぎます！ ");
      _  _  _  _  break;
      _  _  _  }
      _  _  _  else
      _  _  _     sprintf(md[lnb - t] + SentLen - 40 - strlen(egq),".... 翻訳文が長くなり過ぎます！ ");
      _  _  }
      _  }
      _  if (md[lnb - t][1] == 'Z') {
      _  _  if (md[lnb - t][2])
      _  _     ptcut(md[lnb - t] + 1,1);
      _  _  else {
      _  _  _  if (lnb)
      _  _  _     md[lnb - t][0] = '\0';
      _  _  _  else
      _  _  _     md[lnb - t][1] = '\0';
      _  _  }
      _  }
      _  if (md[lnb - t][0] && md[lnb - t][1]) {
      _  _  if (t && (md[lnb - t][0] == 'X') && md[lnb - t + 1][0] && md[lnb - t + 1][1] && strstr("0.??0!",md[lnb - t + 1]))
      _  _     md[lnb - t][1] = toupper(md[lnb - t][1]);
      _  _  if (md[lnb - t][0])
      _  _     ptcut(md[lnb - t],1);
      _  _  ptc = strchr(egq,'/');
      _  _  if ( ptc && (*(ptc + 1)) && strcmp(ptc - 2,"c / o") ) {   /* 分離型訳語の結合 */
      _  _  _  ptp1 = strstr(egq,"（");  /* 上の第３の条件を加えた。2002.10.16 */
      _  _  _  if (ptp1)
      _  _  _     ptp2 = strstr(ptp1 + 2,"）");
      _  _  _  if (ptp1 && ptp2 && (ptp1 < ptc) && (ptc < ptp2))
      _  _  _     strcat(egq,md[lnb - t]);
      _  _  _  else
      _  _  _     ptreplace(ptc,1,md[lnb - t]);
      _  _  }
      _  _  else {
      _  _  _  if (*(egq + 1))
      _  _  _     strcat(egq," ");
      _  _  _  strcat(egq,md[lnb - t]);
      _  _  }
      _  }
      _  ptinsert(jpq,jwn[wc + lnb - t]);
      _  jwn[wc + lnb - t][0] = '\0';
      _  ptinsert(jp0q,jwn0[wc + lnb - t]);
      _  jwn0[wc + lnb - t][0] = '\0';
      _  if ( (cj[wc + lnb - t][0] == '7') && strstr(cz[wc + lnb - t],"|の") ) {
      _  _  ptinsert(jpq,"の");   /* 日本語原文の再構成の厳密化 2004.01.14 */
      _  _  ptinsert(jp0q,"の");
      _  }
      }
   }
   ptc = strstr(egq," @");
   while (ptc) {
   _  ptcut(ptc,2);
   _  ptc = strstr(egq," @");
   }
   ptc = strstr(egq,"  ");
   while (ptc) {
   _  ptcut(ptc,1);
   _  ptc = strstr(egq,"  ");
   }
   egln = strlen(egq);
   while (egq[egln - 1] == ' ') {
   _  egq[egln - 1] = '\0';
   _  --egln;
   }
   strcpy(cj[wc],egq);
   strcpy(jwn[wc],jpq);
   strcpy(jwn0[wc],jp0q);
end


static void narabeKae(void)      /*******   訳語の語順を並べ換える。 *********/
begin                     /* global variables: dumb[], md[][], wc, cz[][] */
   int n0, i1, i2;
   char *pt;

   pt = strstr(dumb,"->");
   while (pt) {
   _  n0 = *(pt - 1);
   _  if (n0 == '<') {
   _  _  i1 = *(pt - 2) - 48;
   _  _  i2 = *(pt + 3) - 48;
   _  _  swap(md[i1],md[i2]);
   _  }
   _  *pt = ' ';
   _  pt = strstr(pt + 3,"->");
   }
end

static int  quote_ck(char jj[], int t)
   /* 引用符の内側には空白を空けない為に、チェックする。*/
   /* 空けない時は 0, 空けてよい時は 1 を返す。*/
begin  /* global variables: lnb, md[][], cz[][], wc  */
   int  ln, rtn = 1;
   char *ptz;

   ln = strlen(jj);
   if ( (strcmp(jj + 1,"\"") == 0) || (strcmp(jj + 1,"\'") == 0) )
      rtn = 0;  /* 2002.09.16 追加した。*/
   else {
   _  if ( (t == 1) && (*(jj + ln - 1) == '\"') && ((ln <= 2) || (*(jj + 1) != '\"')) )
   _     rtn = 0;    /* ３番目の条件を加えた。2002.08.24  */
   _  else {
   _  _  if ( (t == lnb) && ((md[t][1] == '\"') || (md[t][1] == '\'')) ) {
   _  _  _  ptz = md[t] + 2;   /* 2002.09.16 一重引用符の場合を追加した。*/
   _  _  _  if ( (! *ptz) || ((! strchr(ptz,'\"')) && (! strchr(ptz,'\''))) )
   _  _  _     rtn = 0;
   _  _  }
   _  }
   }
   if (rtn && (ln == 5) && strchr(cz[wc + t - 1],'Y') && strchr(cz[wc + t],'Y'))
      rtn = 0;
   if (rtn && (strcmp(jj + ln - 2," ~") == 0)) {
   _  rtn = 0;
   _  *(jj + ln - 2) = '\0';
   }
   return(rtn);
end

static int  akiTsume(char egq[], char md[], int egln)
    /* 訳語が長く成りすぎる時は、余分な空白を削る。 */
begin
   unsigned int  lnold, lnnew;
   char *ptAki, *ptsp, *ptr;

   ptAki = strstr(egq,"  ");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(egq,"  ");
   }
   ptAki = strstr(md,"  ");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(md,"  ");
   }
   ptAki = strstr(egq," .");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(egq," .");
   }
   ptAki = strstr(md," .");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(md," .");
   }
   ptAki = strstr(egq," ?");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(egq," ?");
   }
   ptAki = strstr(md," ?");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(md," ?");
   }
   ptAki = strstr(egq," !");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(egq," !");
   }
   ptAki = strstr(md," !");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(md," !");
   }
   ptAki = strstr(egq," , ");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(egq," , ");
   }
   ptAki = strstr(md," , ");
   while (ptAki) {
   _  ptcut(ptAki,1);
   _  egln--;
   _  ptAki = strstr(md," , ");
   }
   if (egln >= SentLen) {
   _  ptAki = strchr(egq + 2,'(');
   _  while (ptAki) {   /* 動詞の原型情報を削除する。 */
   _  _  ptsp = strchr(ptAki + 2,' ');
   _  _  ptr = strchr(ptAki + 1,')');
   _  _  if (ptr) {
   _  _  _  if ((! ptsp) || (ptr < ptsp)) {
   _  _  _  _  lnold = strlen(egq);
   _  _  _  _  ptptcut(ptAki,ptr);
   _  _  _  _  lnnew = strlen(egq);
   _  _  _  _  egln -= (lnold - lnnew);
   _  _  _  }
   _  _  }
   _  _  else {
   _  _  _  color_red;
   _  _  _  printf("不正レコード   egs = %s \n",egq);
   _  _  _  beeping(10);
   _  _  _  exit(1);
   _  _  }
   _  _  ptAki = strchr(ptAki + 1,'(');
   _  }
   _  ptAki = strchr(md + 2,'(');
   _  while (ptAki) {   /* 動詞の原型情報を削除する。 */
   _  _  ptsp = strchr(ptAki + 2,' ');
   _  _  ptr = strchr(ptAki + 1,')');
   _  _  if (ptr) {
   _  _  _  if ((! ptsp) || (ptr < ptsp)) {
   _  _  _  _  lnold = strlen(md);
   _  _  _  _  ptptcut(ptAki,ptr);
   _  _  _  _  lnnew = strlen(md);
   _  _  _  _  egln -= (lnold - lnnew);
   _  _  _  }
   _  _  }
   _  _  else {
   _  _  _  color_red;
   _  _  _  printf("不正レコード   egs = %s \n",md);
   _  _  _  beeping(10);
   _  _  _  exit(1);
   _  _  }
   _  _  ptAki = strchr(ptAki + 1,'(');
   _  }
   }
   if (egln >= SentLen) {
   _  ptAki = strstr(egq + 2,"(s)");
   _  while (ptAki) {   /* 名詞の複数型情報を削除する。 */
   _  _  if ( (! *(ptAki + 3)) || (*(ptAki + 3) == ' ') ) {
   _  _  _  _  ptcut(ptAki,3);
   _  _  _  _  egln -= 3;
   _  _  }
   _  _  ptAki = strstr(egq + 2,"(s)");
   _  }
   _  ptAki = strstr(md + 2,"(s)");
   _  while (ptAki) {   /* 名詞の複数型情報を削除する。 */
   _  _  if ( (! *(ptAki + 3)) || (*(ptAki + 3) == ' ') ) {
   _  _  _  _  ptcut(ptAki,3);
   _  _  _  _  egln -= 3;
   _  _  }
   _  _  ptAki = strstr(egq + 2,"(s)");
   _  }
   }
   return(egln);
end


static void czConnec(char cd)    /* 属性変数を結合する。 */
begin                        /* global variables: wc, te, cj[], cz[], jwn[] */

   int t, lnt, lnz;
   char *pt, *ptCk, *ptm1, *ptmt;
   char czq[SentZokuLen];

   ptCk = strchr(cz[wc],'?');
   if (cz[wc][0] == 'Y')
      ptcut(cz[wc],1);
   czDel(wc,cd); /* 形容詞、副詞の属性は「御用済み」なので結合時に消去する。*/
   lnz = strlen(cz[wc]);
   for (t = wc + 1; t <= te; t++) {
   _  ptmt = strchr(cz[t],'|');
   _  if (cj[t][0] == '7') {
   _  _  *czq = '\0';   /* 前置詞('7')の属性は消去する。*/
   _  _  if (ptmt)
   _  _     strcat(czq,ptmt);
   _  _  strcpy(cz[t],czq);
   _  }
   _  if (cz[t][0] == 'Y') {
   _  _  if (ptmt)
   _  _     ptptcut(cz[t],ptmt - 1);
   _  _  else
   _  _     cz[t][0] = '\0';
   _  }
   _  else                      /* 辞書にない単語('Y')の属性は消去する。*/
   _     czDel(t,cd);
		/* 形容詞、副詞の属性は「御用済み」なので結合時に消去する。*/
   _  if (ptCk) {
   _  _  pt = strchr(cz[t],'?');
   _  _  while (pt) {
   _  _  _  ptcut(pt,1);
   _  _  _  pt = strchr(cz[t],'?');
   _  _  }
   _  }
   _  lnt = strlen(cz[t]);
   _  ptm1 = strchr(cz[wc],'|');
   _  if (lnt)
   _     ptmt = strchr(cz[t],'|');
   _  else
   _     ptmt = (char*) 0;
   _  if (lnz + lnt < (SentZokuLen - 4)) {
   _  _  zokuConn(t,lnt,ptmt,ptm1); /* cz[wc]とcz[t]の第１属性値を結合する */
   _  _  lnz += lnt;
   _  }
   _  else {
   _  _  if ((! strstr(cz[wc],"!Cut!")) && (! strstr(cz[t],"!Cut!")))
   _  _     lnz = czShorten(t); /* cz[] を SentZokuLen 文字以内に縮める。 */
   _  }
   _  ptm1 = strstr(cz[wc],"||");
   _  if (ptm1)
   _     ptcut(ptm1,1);
   _  cj[t][0] = '\0';
   _  cz[t][0] = '\0';
   }
end


static void zokuConn(int t, int lnt, char *ptmt, char *ptm1)
	 /* 属性を語順の逆に結合する。*/
begin  /* global variables: wc, cj[][], cz[][] */
   char *ptty, *ptwcy,josuushi[SentZokuLen];

   if (lnt && ptmt && *(ptmt + 1)) {
   _  if (ptm1)
   _     ptinsert(ptm1 + 1,ptmt + 1);
   _  else
   _     strcat(cz[wc],ptmt);
   }
   if (ptmt)
      *ptmt = '\0';
   if (lnt) {
   _  ptty = strchr(cz[t],'y');
   _  if ((cj[wc][0] == '1') && (cj[t][0] == '1')) {
   _  _  ptwcy = strchr(cz[wc],'y');
   _  _  if ( ptwcy && ((! ptm1) || (ptwcy < ptm1)) ) {
    /* 第２属性の全角文字コードに 'y' が含まれる場合を除く為に */
    /* 上式の第２条件を加えた。2002.12.06 */
   _  _  _  if (ptty && *(ptty + 1)) {
   _  _  _  _  strcpy(josuushi,ptty + 1);
   _  _  _  _  *ptty = '\0';
   _  _  _  _  ptinsert(ptwcy + 1,josuushi);
   _  _  _  }
   _  _  _  ptinsert(ptwcy,cz[t]);
   _  _  }
   _  _  else {
   _  _  _  if (ptty && ptm1)
   _  _  _     ptinsert(ptm1,cz[t]);
   _  _  _  else
   _  _  _     ptinsert(cz[wc],cz[t]);
   _  _  }
   _  }
   _  else {
   _  _  if (ptty && ptm1)
   _  _     ptinsert(ptm1,cz[t]);
   _  _  else
   _  _     ptinsert(cz[wc],cz[t]);
   _  }
   }
end


static void czDel(int t, char cd)
                /* 形容詞、副詞の属性は「御用済み」なので結合時に消去する。*/
begin           /* global variables: wc, cj[][], cz[][] */
   char dumz[SentZokuLen];

   if (((cj[t][0] == '5') || (cj[t][0] == '6')) && (! strchr("356",cd))) {
   _  *dumz = '\0';
   _  if (strchr(cz[t],'N'))
   _     strcpy(dumz,"N");
   _  if (strchr(cz[t],'n'))
   _     strcat(dumz,"n");
   _  if (strchr(cz[t],'U'))
   _     strcat(dumz,"U");
   _  if (strchr(cz[t],'O'))
   _     strcat(dumz,"O");
   _  if (strchr(cz[t],'r'))
   _     strcat(dumz,"r");
   _  strcpy(cz[t],dumz);
   }
end

static int  czShorten(int t)
			      /* cz[] を 37 文字以内に縮める。 */
begin   /* global variables: wc, cz[][], cj[][] */
   register int  i;
   int   j, d = 0;
   char  dumz[70], baikaku[3], *ptw, *ptz, *ptt, *ptp, *dumz_8;

   for (i = 0; i < 69; i++)
      dumz[i] = '\0';
   j = -1;
   ptw = strchr(cz[wc],'|');
   for (i = 0; i <= (SentZokuLen - 1); i++) {
   _  if ((! cz[wc][i]) || (cz[wc][i] == '|'))
   _     break;
   _  if (! strchr(dumz,cz[wc][i]))
   _     dumz[++j] = cz[wc][i];
   }           /* cz[wc] の第１属性を dumz[] にコピーした。*/
   for (i = 0; i <= (SentZokuLen - 1); i++) {
   _  if ((! cz[t][i]) || (cz[t][i] == '|'))
   _     break;
   _  if (! strchr(dumz,cz[t][i]))
   _     dumz[++j] = cz[t][i];
   }               /* cz[t] の第１属性も dumz[] にコピーした。*/
   dumz[++j] = '|';
   ptz = dumz + j;
   ptw = strchr(cz[wc],'|');
   if (ptw) {
   _  ++ptw;                /* cz[wc] の第２属性を dumz[] に結合する。*/
   _  while (*ptw) {
   _  _  if (*ptw == '(') {
   _  _  _  ptp = strchr(ptw + 1,')');
   _  _  _  if (ptp) {
   _  _  _  _  ptcpy(dumz + j + 1,ptw,ptp + 1);
   _  _  _  _  j = strlen(dumz) - 1;
   _  _  _  _  ptw = ptp + 1;
   _  _  _  }
   _  _  _  else {
   _  _  _  _  if (! strstr(ptw,"!Cut!")) { /* 2001.01.18 この条件を付けた。*/
   _  _  _  _  _  beeping(5);
   _  _  _  _  _  printf("\n\n 第2属性の括弧エラー！！ Case W: cz[wc] = %s \n ptw = %s \n",cz[wc],ptw);
   _  _  _  _  _  exit(1);
   _  _  _  _  }
   _  _  _  }
   _  _  }
   _  _  else {
   _  _  _  if (*(ptw + 1))
   _  _  _     ptcpy(baikaku,ptw,ptw + 2);
   _  _  _  else
   _  _  _     *baikaku = '\0';
   _  _  _  if ((! *baikaku) || (isalnum(*ptw) && (*ptw != (- 108)) && (! strstr("OJ,SJ,VR,rD,は,が,単,複",baikaku))) ) {
   _  _  _  _  if (! strchr(ptz,*ptw))
   _  _  _  _     dumz[++j] = *ptw;
   _  _  _  _  ++ptw;
   _  _  _  }
   _  _  _  else {
   _  _  _  _  if (! strstr(ptz,baikaku)) {
   _  _  _  _  _  strcat(dumz,baikaku);
   _  _  _  _  _  j += 2;
   _  _  _  _  }
   _  _  _  _  ptw += 2;
   _  _  _  }
   _  _  }
   _  }
   }
   ptt = strchr(cz[t],'|');
   if (ptt) { /* cz[t] の第２属性を dumz[] に結合する。*/
   _  ++ptt;
   _  while (*ptt) {
   _  _  j = strlen(dumz) - 1;
   _  _  if (j >= (SentLen + 15))
   _  _     break;
   _  _  if (*ptt == '(') {
   _  _  _  ptp = strchr(ptt + 1,')');
   _  _  _  if (ptp) {
   _  _  _  _  ptcpy(dumz + j + 1,ptt,ptp + 1);
   _  _  _  _  j = strlen(dumz) - 1;
   _  _  _  _  ptt = ptp + 1;
   _  _  _  }
   _  _  _  else {
   _  _  _  _  if (! strstr(ptt,"!Cut!")) { /* 2001.01.18 この条件を付けた。*/
   _  _  _  _  _  beeping(5);
   _  _  _  _  _  printf("\n\n 第2属性の括弧エラー！！ Case t: cz[t] = %s \n ptt = %s \n",cz[t],ptt);
   _  _  _  _  _  exit(1);
   _  _  _  _  }
   _  _  _  }
   _  _  }
   _  _  else {
   _  _  _  if (*(ptt + 1))
   _  _  _     ptcpy(baikaku,ptt,ptt + 2);
   _  _  _  else
   _  _  _     *baikaku = '\0';
   _  _  _  if ((! *baikaku) || (isalnum(*ptt) && (*ptt != (- 108)) && (! strstr("OJ,SJ,VR,rD",baikaku))) ) {
   _  _  _  _  if (! strchr(ptz,*ptt))
   _  _  _  _  _     dumz[++j] = *ptt;
   _  _  _  _  ++ptt;
   _  _  _  }
   _  _  _  else {
   _  _  _  _  if (! strstr(ptz,baikaku)) {
   _  _  _  _  _  strcat(dumz,baikaku);
   _  _  _  _  _  j += 2;
   _  _  _  _  }
   _  _  _  _  ptt += 2;
   _  _  _  }
   _  _  }
   _  }
   }
   j = strlen(dumz) - 1;
   if (j < SentZokuLen - 1)
      strcpy(cz[wc],dumz);
   else {
/*   _  printf("cz[wc] will exceed SentZokuLen characters. j = %d, dumz = %s \n",j,dumz); */
/*   _  printf("  cz[t] = %s,  Remainder of cz[t] = %s \n",cz[t], cz[t] + i); */
   _  dumz_8 = dumz + SentZokuLen - 8;
   _  if (strchr(dumz_8,')') && (! strchr(dumz_8,'(')))
   _     dumzShorten(dumz,dumz_8);
   _  else {
   _  _  ptcpy(cz[wc],dumz, dumz + SentZokuLen - 8);
   _  _  strcat(cz[wc],"!Cut!");
/*   _  _  printf(" new cz[wc] = %s \n",cz[wc]); */
   _  }
   }
   return(strlen(dumz));
end

static void  dumzShorten(char dumz[], char *dumz_8)
     /* 属性変数 cz[] の仮変数 dumz[] の括弧部分を切り落とす。 */
begin
  int  err = 0;
  char *ptp, *ptp0, *ptt;

  ptp = dumz;
  while (ptp) {
  _  ptp0 = ptp;
  _  ptt = strchr(ptp + 1,')');
  _  if (ptt && (ptt < dumz_8))
  _     ptp = strchr(ptt + 1,'(');
  _  else
  _    break;
  }
  *ptp0 = '\0';
end


static void bpoDbg(void)  /* 文法規則とその適用結果を画面に表示する。*/
begin              /* global variables: pbun[], wnb, cj[][], cz[][] */
   register int t, ln;

   printf("\n\n\n");
   color_light_blue;
   printf("pbun = %s  \n",pbun);
   color_white;
#if defined(USER)
   if (Dbg2 == 'Y') {
   _  fprintf(dbgfl_pt,"\n\n");
   _  fprintf(dbgfl_pt,"pbun = %s  \n",pbun);
   }
#endif
   for (t = 0; t <= wnb; t++) {
   _  ln = strlen(cj[t]);
   _  if (ln < 14) {
   _  _  printf("cj[%d] = ",t);
   _  _  color_magenta;
   _  _  printf("%c",cj[t][0]);
   _  _  color_white;
   _  _  printf("%-14s",cj[t] + 1);
   _  }
   _  else {
   _  _  if (ln < 24) {
   _  _  _  printf("cj[%d] = ",t);
   _  _  _  color_magenta;
   _  _  _  printf("%c",cj[t][0]);
   _  _  _  color_white;
   _  _  _  printf("%-24s",cj[t] + 1);
   _  _  }
   _  _  else {
   _  _  _  printf("cj[%d] = ",t);
   _  _  _  color_magenta;
   _  _  _  printf("%c",cj[t][0]);
   _  _  _  color_white;
   _  _  _  printf("%s\n",cj[t] + 1);
   _  _  _  printf("%-23s","   ");
   _  _  }
   _  }
   _  color_green;
   _  printf("cz[%d] = %s  \n",t,cz[t]);
#if defined(USER)
   _  if (Dbg2 == 'Y') {
   _  _  if (ln < 14)
   _  _     fprintf(dbgfl_pt,"cj[%d] = %-15s",t,cj[t]);
   _  _  else {
   _  _  _  if (ln < 24)
   _  _  _     fprintf(dbgfl_pt,"cj[%d] = %-25s",t,cj[t]);
   _  _  _  else {
   _  _  _  _  fprintf(dbgfl_pt,"cj[%d] = %s\n",t,cj[t]);
   _  _  _  _  fprintf(dbgfl_pt,"%-23s","   ");
   _  _  _  }
   _  _  }
   _  _  fprintf(dbgfl_pt,"cz[%d] = %s  \n",t,cz[t]);
   _  }
#endif
   _  color_white;
   _  pause(1000);
   }
end

  /* 単語結合の過程を図示する関数 */
static void Draw_tree_main (char *dz[100][100], int pos[100], char jnold[100][100], int iorig, int wnb2)
begin
   int i, i2, j, k = 0, jnlen[100], enlen[100][100], sa, jwdpt[100], ewdpt[100], wdcenter[100][100], wdtop[100], wdbottom[100], wnb3[100]={wnb2};
   FILE *tree_file;

   tree_file = fopen ("tree", "a");
   if (! tree_file)
        printf("\n file 'tree' could not be opened!!");
     /* *********************** DBG *********************** */
      printf("\n Entered Draw_tree_main(); iorig = %d, wnb2 = %d,",iorig,wnb2);
      /* *********************** DBG *********************** */
    for (i = 0; i < iorig; i++) {
   /* 初期状態の書き出し */
   _  if(i == 0) {
   /* 日本語単語と英単語の表示位置を格納する変数の初期化処理 */
   _  _  for(j = 0; j <= wnb2; j++) {
   _  _  _  jwdpt[j] = 0;
   _  _  _  ewdpt[j] = 0;
   _  _  }
   /* 日本語単語書き込み位置算出 */
   _  _  for(j = 0; j <= wnb2; j++) {
   /* 日本語単語と英単語の長さをそれぞれ格納 */
   _  _  _  jnlen[j] = strlen(jnold[j]);
   _  _  _  enlen[0][j] = strlen(dz[i][j]);
   /* 日本語単語の方が英単語よりも長い時 */
   _  _  _  if(jnlen[j] >= enlen[0][j]) {
   _  _  _  _  jwdpt[j] += 3;
   _  _  _  _  jwdpt[j+1] = jwdpt[j] + jnlen[j];
   _  _  _  }
   /* 英単語の方が日本語単語よりも長い時 */
   _  _  _  else {
   _  _  _  _  jwdpt[j] += 3;
   _  _  _  _  jwdpt[j+1] = jwdpt[j] + enlen[0][j];
   /* 英単語との差分を足しておく */
   _  _  _  _  jwdpt[j] += (enlen[0][j] - jnlen[j]) / 2;
   _  _  _  }
   _  _  }

   /* 英単語書き込み位置算出 */
   _  _  for(j = 0; j <= wnb2; j++) {
   /* 英単語の方が日本語単語よりも長い時 */
   _  _  _  if(jnlen[j] <= enlen[0][j]) {
   _  _  _  _  ewdpt[j] += 3;
   _  _  _  _  ewdpt[j+1] += ewdpt[j] + enlen[0][j];
   _  _  _  }
   /* 日本語単語の方が英単語よりも長い時 */
   _  _  _  else {
   _  _  _  _  ewdpt[j] += 3;
   _  _  _  _  ewdpt[j+1] += ewdpt[j] + jnlen[j];
   /* 日本語単語との差分を足しておく */
   _  _  _  _  ewdpt[j] += (jnlen[j] - enlen[0][j]) / 2;
   _  _  _  }
   _  _  }
   _  _  wnb2 = Def_wdcenter (tree_file, iorig, enlen, jwdpt, ewdpt, wnb2, i, pos, k, wdcenter, wdtop, wdbottom, wnb3);
   _  }

   _  else {

   /* 文法規則適用後の単語の長さ格納 */
   _  _  for(j = 0; j <= wnb2; j++)
   _  _  _  enlen[i][j] = strlen(dz[i][j]);

   /* 単語の先頭と末尾の位置をそれぞれ格納 */
   _  _  wdtop[i] = wdcenter[i][pos[k]] - enlen[i][pos[k]] / 2 - 1;
   _  _  wdbottom[i] = wdtop[i] + enlen[i][pos[k]];

   /* 単語の先頭がファイルの左端よりも左になってしまう場合 */
   _  _  if(wdtop[i] < 0) {
   _  _  _  i2 = i;
   _  _  _  sa = 0 - wdtop[i] + 2;
   _  _  _  for(; i2 >= 0; i2--) {
   _  _  _  _  for(j = 0; j <= wnb3[i2]; j++)
   _  _  _  _  _  wdcenter[i2][j] += sa;
   _  _  _  }
   _  _  _  for (j = 0; j <= wnb3[0]; j++) {
   _  _  _  _  jwdpt[j] += sa;
   _  _  _  _  ewdpt[j] += sa;
   _  _  _  }
   _  _  _  wdtop[i] = wdcenter[i][0] - enlen[i][0] / 2 - 1;
   _  _  _  wdbottom[i] = wdtop[i] + enlen[i][0];
   _  _  }
   _  _  k += 2;

   _  _  wnb2 = Def_wdcenter (tree_file, iorig, enlen, jwdpt, ewdpt, wnb2, i, pos, k, wdcenter, wdtop, wdbottom, wnb3);
   _  }
   }
   Draw_tree (tree_file,iorig, pos, wnb3, jwdpt, ewdpt, wdcenter, wdtop, wdbottom, dz, jnold, jnlen, enlen);

   fclose(tree_file);
end


/* 線を引くポイントを決定する関数 */
static int Def_wdcenter (FILE *tree_file, int iorig, int enlen[][100], int jwdpt[], int ewdpt[], int wnb2, int i, int pos[100], int k, int wdcenter[][100], int wdtop[], int wdbottom[], int wnb3[])
begin
   int i2, j, j2, linept, lis[100][100], sa;

/* 各単語の中心の位置をwdcenter[][]に格納 */
   if (i == 0) {
   _  for (j = 0; j <= wnb2; j++) {
   _  _  _  wdcenter[0][j] = ewdpt[j] + enlen[0][j] / 2;
   _  }

   /* 各ステップの単語結合をリストに保存（初期状態） */
   _  for(j = 0; j <= wnb2; j++)
   _  _  lis[i][j] = j;
   _  }

   _  wnb2 = wnb2 - (pos[k+1] - pos[k]);   /* 残り単語数の変更 */
   _  wnb3[i+1]=wnb2;     /* 各ステップの残り単語数を保持 */

   /* 各ステップの単語結合をリストに保存 */
   _  if (i > 0) {
   _  _  j2 = 0;
   _  _  for(j = 0; j <= wnb3[i]; j++) {
   _  _  _  lis[i][j] = j2;
   _  _  _  j2++;
   _  _  _  if(j==pos[k-2])
   _  _  _  _  j2=pos[k-1]+1;
   _  _  }
   _  }

   /* 文字と線が重なるのを防ぐ作業(前) */
   _  if(i > 0 && pos[k-2] != 0) {
   _  _  if(wdtop[i] <= wdcenter[i][pos[k-2]-1]) {
   _  _  _  i2 = i;
   _  _  _  j = pos[k-2];
   _  _  _  sa = wdcenter[i2][j-1] - wdtop[i2] + 2;
   _  _  _  for(; i2 >= 0; i2--) {
   _  _  _  _  j2 = lis[i2][j];
   _  _  _  _  for(; j <= wnb3[i2]; j++)
   _  _  _  _  _  wdcenter[i2][j] += sa;
   _  _  _  _  j = j2;
   _  _  _  }
   _  _  _  for (j2 = lis[0][j]; j <= wnb3[0]; j++) {
   _  _  _  _  jwdpt[j] += sa;
   _  _  _  _  ewdpt[j] += sa;
   _  _  _  }
   _  _  _  wdtop[i] = wdcenter[i][pos[k-2]] - enlen[i][pos[k-2]] / 2 - 1;
   _  _  _  wdbottom[i] = wdtop[i] + enlen[i][pos[k-2]];
   _  _  }
   _  }

   /* 文字と線が重なるのを防ぐ作業(後ろ) */
   _  if(i > 0 && pos[k-1] != wnb3[i-1]) {
   _  _  if(wdbottom[i] >= wdcenter[i][pos[k-2]+1]) {
   _  _  _  i2 = i;
   _  _  _  j = pos[k-2]+1;
   _  _  _  sa = wdbottom[i2] - wdcenter[i2][j] + 2;
   _  _  _  for(; i2 >= 0; i2--) {
   _  _  _  _  j2 = lis[i2][j];
   _  _  _  _  for(; j <= wnb3[i2]; j++)
   _  _  _  _  _  wdcenter[i2][j] += sa;
   _  _  _  _  j = j2;
   _  _  _  }
   _  _  _  for (j2 = lis[0][j]; j <= wnb3[0]; j++) {
   _  _  _  _  jwdpt[j] += sa;
   _  _  _  _  ewdpt[j] += sa;
   _  _  _  }
   _  _  }
   _  }

   /* 次のwdcenter[][]の値を決定 */
   _  for (j = 0; j <= wnb2; j++) {
   _  _  if (j < pos[k])
   _  _  _  wdcenter[i+1][j] = wdcenter[i][j];
   _  _  else if (j == pos[k])
   _  _  _  wdcenter[i+1][j] = wdcenter[i][pos[k]] + ((wdcenter[i][pos[k+1]] - wdcenter[i][pos[k]]) / 2);
   _  _  else
   _  _  _  wdcenter[i+1][j] = wdcenter[i][j+(pos[k+1]-pos[k])];
   _  }

   /* 最終ステップまで来ている時 */
   _  if(i == iorig - 1)
   _  _  lastwd = wdcenter[i + 1][0];

   _  return wnb2;
end

/* 実際にファイルへ図の書き込みを行なう関数 */
static void Draw_tree(FILE *tree_file, int iorig, int pos[100], int wnb3[], int jwdpt[], int ewdpt[], int wdcenter[][100], int wdtop[], int wdbottom[], char *dz[][100], char jnold[][100], int jnlen[], int enlen[][100])
begin
  int i, j, k=0, linept=0;

/* 日本語単語書き込み */
  for(j = 0; j <= wnb3[0]; j++) {
  _  while (linept < jwdpt[j]) {
  _  _  fprintf(tree_file," ");
  _  _  linept++;
  _  }
  _  fprintf(tree_file,"%s",jnold[j]);
  _  linept += strlen(jnold[j]);
  }

  fprintf(tree_file,"\n");
  linept = 0;

/* 英単語書き込み */
  for(j = 0; j <= wnb3[0]; j++) {
  _  while (linept < ewdpt[j]) {
  _  _  fprintf(tree_file," ");
  _  _  linept++;
  _  }
  _  fprintf(tree_file,"%s",dz[0][j]);
  _  linept += strlen(dz[0][j]);
  }

  fprintf(tree_file,"\n");
  linept=0;

  for(i = 0; i < iorig; i++) {
    /* 線１行目 */
  _  for(j = 0; j <= pos[k]; j++) {
  _  _  while(linept < wdcenter[i][j]) {
  _  _  _  fprintf(tree_file," ");
  _  _  _  linept++;
  _  _  }
  _  _  fprintf(tree_file,"|");
  _  _  linept++;
  _  }
  _  for( ; j <= pos[k+1]; j++) {
  _  _  while(linept < wdcenter[i][j]) {
  _  _  _  fprintf(tree_file,"_");
  _  _  _  linept++;
  _  _  }
  _  _  fprintf(tree_file,"|");
  _  _  linept++;
  _  }
  _  for( ; j <= wnb3[i]; j++) {
  _  _  while(linept < wdcenter[i][j]) {
  _  _  _  fprintf(tree_file," ");
  _  _  _  linept++;
  _  _  }
  _  _  fprintf(tree_file,"|");
  _  _  linept++;
  _  }
  _  fprintf(tree_file,"\n");
  _  linept = 0;

    /* 線２行目 */
  _  for(j = 0; j <= wnb3[i+1]; j++) {
  _  _  while(linept < wdcenter[i+1][j]) {
  _  _  _  fprintf(tree_file," ");
  _  _  _  linept++;
  _  _  }
  _  _  fprintf(tree_file,"|");
  _  _  linept++;
  _  }
  _  fprintf(tree_file,"\n");
  _  linept = 0;

    /* 文法規則適用後の単語書き込み */
  _  if(i+1 < iorig) {
  _  _  for(j = 0; j < pos[k]; j++) {
  _  _  _  while(linept < wdcenter[i+1][j]) {
  _  _  _  _  fprintf(tree_file," ");
  _  _  _  _  linept++;
  _  _  _  }
  _  _  _  fprintf(tree_file,"|");
  _  _  _  linept++;
  _  _  }
  _  _  while(linept < (wdcenter[i+1][pos[k]] - enlen[i+1][pos[k]] / 2)) {
  _  _  _  fprintf(tree_file," ");
  _  _  _  linept++;
  _  _  }
  _  _  fprintf(tree_file,"%s",dz[i+1][pos[k]]);
  _  _  linept += enlen[i+1][pos[k]];
  _  _  j++;
  _  _  for( ; j <= wnb3[i+1]; j++) {
  _  _  _  while(linept < wdcenter[i+1][j]) {
  _  _  _  _  fprintf(tree_file," ");
  _  _  _  _  linept++;
  _  _  _  }
  _  _  _  fprintf(tree_file,"|");
  _  _  _  linept++;
  _  _  }
  _  _  fprintf(tree_file,"\n");
  _  _  linept = 0;
  _  _  k += 2;
  _  }
  }
end
