/* Copyright (c) 1991-2002 Doshita Lab. Speech Group, Kyoto University */
/* Copyright (c) 2000-2002 Speech and Acoustics Processing Lab., NAIST */
/*   All rights reserved   */

/* init_dfa.c --- initialize DFA */

/* $Id: init_dfa.c,v 1.5 2003/01/06 08:05:37 ri Exp $ */

#include <sent/stddefs.h>
#include <sent/dfa.h>
#include <sent/vocabulary.h>
#include <sent/htk_hmm.h>

/* read in dfa info from file */
void
init_dfa(DFA_INFO *dinfo, char *filename) /* DFA file -> dinfo */
{
  FILE *fd;
  
  j_printerr("Reading in DFA grammar...");
  if ((fd = fopen_readfile(filename)) == NULL) {
    j_error("failed to open %s\n",filename);
  }
  if (!rddfa(fd, dinfo)) {
    j_error("error in reading %s\n",filename);
  }
  if (fclose_readfile(fd) == -1) {
    j_error("close error\n");
  }

  j_printerr("done\n");
}

/* map words in .dict to terminal symbol in .dfa */
void
make_dfa_voca_ref(DFA_INFO *dinfo, WORD_INFO *winfo)
{
  int i;
  boolean okflag = TRUE;

  j_printerr("Mapping dict item <-> DFA terminal (category)...");
  /* word -> terminal symbol */
  for (i = 0; i < winfo->num; i++) {
    winfo->wton[i] = dfa_symbol_lookup(dinfo, winfo->wname[i]);
    if (winfo->wton[i] == WORD_INVALID) {
      /* error: not found */
      j_printerr("Error: no such terminal symbol \"%s\" in DFA grammar:\n",
	     winfo->wname[i]);
      put_voca(winfo, i);
      okflag = FALSE;
    }
  }
  if (!okflag) j_error("Error in dict <-> DFA mapping\n");

  /* terminal symbol -> word */
  make_terminfo(&(dinfo->term), dinfo, winfo);
  
  j_printerr("done\n");
}

/* set dfa->sp_id and dfa->is_sp[cate] from hmminfo->sp */
void
dfa_find_pause_word(DFA_INFO *dfa, WORD_INFO *winfo, HTK_HMM_INFO *hmminfo)
{
  HMM_Logical *sphmm;
  int i, t,p;
  WORD_ID w;

  dfa->sp_id = WORD_INVALID;
  dfa->is_sp = (boolean *)mymalloc(sizeof(boolean) * dfa->term_num);
  for(t=0;t<dfa->term_num;t++) dfa->is_sp[t] = FALSE;
  
  for(t=0;t<dfa->term_num;t++) {
    for(i=0;i<dfa->term.wnum[t]; i++) {
      w = dfa->term.tw[t][i];
      p = 0;
      while(p < winfo->wlen[w] && winfo->wseq[w][p] == hmminfo->sp) p++;
      if (p >= winfo->wlen[w]) {	/* w consists of only hmminfo->sp model */
	dfa->is_sp[t] = TRUE;
	if (dfa->sp_id == WORD_INVALID) dfa->sp_id = w;
	break;			/* mark this category if at least 1 sp_word was found */
      }
    }
  }
}

void
dfa_pause_word_append(DFA_INFO *dst, DFA_INFO *src, int coffset)
{
  int i;
  /* dst info must be already appended */
  /* [coffset..dst->term_num-1] is the new categories */
  if (dst->term_num - coffset != src->term_num) {
    j_error("InternalError: appended term num not match!\n");
  }
  
  if (dst->is_sp == NULL) {
    dst->is_sp = (boolean *)mymalloc(sizeof(boolean) * dst->term_num);
  } else {
    dst->is_sp = (boolean *)myrealloc(dst->is_sp, sizeof(boolean) * dst->term_num);
  }
  for(i=0;i<src->term_num;i++) {
    dst->is_sp[coffset+i] = src->is_sp[i];
  }
  if (dst->sp_id == WORD_INVALID) {
    if (src->sp_id != WORD_INVALID) {/* src has pause word */
      dst->sp_id = src->sp_id;
    }
  }
}
