/* FILE TALD3E_SM_EXPORT.C; exportized version of:       */
/*********************************************************/
/* tald3e_sm.c - tests recursive alignment distance fcn  */
/* by creating file of phonological alignments based on  */
/* contents of an input alignment file.                  */
/* This version does split/merge alignment.              */
/*                                                       */
/* Synopsis: tald3e_sm <parms>, where:                   */
char *parms = "fname_aln_out fname_aln_in fname_pcdtab fname_ttp_pcdrls sylb_data_dir fom_threshold lim (db_level)";
/*                                                       */
/* Input:                                                */
/*   the old alignments from file "fname_aln_in"         */
/* Output:                                               */
/*   new alignments into file "fname_aln_out             */
/* Parameters:                                           */
/*   fname_pcdtab: name of file containing a tabular     */
/*     definition of the particular phonological code    */
/*     sets (pcodesets) to be used.                      */
/*   fname_ttp_pcdrls: name of file containing TTP rules */
/*     for making new lexicon entries, as a pcodeset.    */
/*   sylb_data_dir: directory where syllabification data */
/*     can be found.                                     */
/*   fom_threshold: if split/merge figure of merit (fom) */
/*     is greater than this value, s/m hypothesis is     */
/*     accepted.  Typical value would be 1.50.           */
/*   lim: arbitrary limit to the number of alignments    */
/*     that will be processed (for testing).             */
/*   db_level: level of printout of intermediate results */
/*     (de-bug print-outs); 0 for none, 1 for a few, etc.*/
/*                                                       */
/* Author: W. M. Fisher, NIST                            */
/* Release history:                                      */
/*   DATE  VER DESCRIPTION                               */
/* 4/16/99 1.2 Generalize so that top-level code set can */
/*             be either words or phones.                */
/*  1/4/99 1.1 Make memory allocation dynamic, tune fcns.*/
/*  6/8/98 1.0 Major improvement to TTP function that is */
/*     used to make prons for words not in dictionary,   */
/*     fixed all memory leaks.                           */
/* 12/5/97 0.1 Includes fixes to one bug that would be   */
/*     triggered if two candidate s/m's are close enough */
/*     to conflict, and some memory allocation and       */
/*     initialization problems.                          */
/*10/15/97 0.0 Original release.                         */
/*********************************************************/


/* standard compile environment for programs: */
/* #include <gp/stdcenvp.h> */ /* NIST version only */
#include "./hdrs/stdcenvp.h"  /* export version only */


int main(int argc, char *argv[])
 {char *proc = "tald3e_sm";
  char *ver_no = "Ver. 1.2";
  TABLE_OF_CODESETS codesets, *pcdtab = &(codesets);
  pcodeset *pcode_x, *pcode_word, *pcode_phon, *pcode1;
  pcodeset ttp_pcdrls_data, *ttp_pcdrls = &ttp_pcdrls_data;
  struct BPATH ttp_bpath_data, *ttp_bpath = &ttp_bpath_data;
  struct SYL_PARMS ttp_syl_parm_data, *ttp_syl_parms = &ttp_syl_parm_data;
  TTP_PCDRLS_PARAMETERS ttparmx, *ttp_pcdrls_parms = &ttparmx;
  PROTECTED_CHR_STR *nsx;
  char *fname_pcdtab, *fname_ttp_pcdrls, *fname_aln_in, *fname_aln_out;
  char *sylb_data_dir;
  char *path, ttp_tgbound = '.';
  ALIGNMENT_INT_PROT *p1,*p2;
  ALIGNMENT_CHR_PROT *ps1;
  boolean return_alignment = T, at_end, print_sms = T;
  boolean sm_header_printed = F;
  int d, nal_total, lim, err,*perr = &err;
  int i, ichr, jchr;
  double fom_threshold;
  FILE *fp_in, *fp_out; /* corpus file */
  time_t t_sec;
/*   code   */
/* global initialization */
  t_sec = time(&t_sec);      /* ANSI, Turbo C */
  pdb = strcpy(pdb,"*DB: ");
  detail_level = 0;
  nsx = create_prot_chr_str(133);
  pcdtab->ncodesets = 0;
/* get command line parameters */
  if (argc < 8)
    {fprintf(stdout,"Usage: %s %s\n",proc,parms);
     return -1;
    }
  fname_aln_out     = argv[1];
  fname_aln_in      = argv[2];
  fname_pcdtab      = argv[3];
  fname_ttp_pcdrls  = argv[4];
  sylb_data_dir     = argv[5];
  fom_threshold     = atof(argv[6]);
  lim               = atoi(argv[7]);
  if (argc > 8) db_level = atoi(argv[8]); else db_level = 0;
/* report basics */
  fprintf(stdout," Program %s %s Report.\n",proc,ver_no);
  fprintf(stdout,"\n");
  fprintf(stdout," Produces new alignment file from old.\n");
  fprintf(stdout," Run %s.\n",del_eol(ctime(&t_sec)));
  fprintf(stdout,"\n");
  fprintf(stdout," Command line parameters:\n");
  fprintf(stdout,"   Old alignments file: '%s'\n",fname_aln_in);
  fprintf(stdout,"   New alignments file: '%s'\n",fname_aln_out);
  fprintf(stdout,"   pcode   table  file: '%s'\n",fname_pcdtab);
  fprintf(stdout,"   TTP   pcdrls   file: '%s'\n",fname_ttp_pcdrls);
  fprintf(stdout,"   sylb data directory: '%s'\n",sylb_data_dir);
  fprintf(stdout,"   fom threshold: %f\n",fom_threshold);
  fprintf(stdout,"   output limit: %d triples\n",lim);
  fprintf(stdout,"   db_level: %d\n",db_level);
/* get codesets */
  get_code_table(pcdtab, fname_pcdtab, &err);
  if (err > 10)
    {fprintf(stdout," *ERR:Get_code_table returned err code =%d\n",err);
     fprintf(stdout," file: '%s'\n",fname_pcdtab);
     return 1;
    }
if (db_level > 0) dump_code_table(pcdtab);
  if (pcdtab->ncodesets < 0)
    {fprintf(stdout,"; *ERR:Get_code_table returns ncodesets < 1\n");
     return 2;
    }
/* find word and phon pcodesets */
  pcode_word = NULL;
  pcode_phon = NULL;
  for (i = 1; i <= pcdtab->ncodesets; i++)
    {pcode_x = pcdtab->cd[i].pc;
     if (strstr(pcode_x->element_type,"word")) pcode_word = pcode_x;
     if (strstr(pcode_x->element_type,"phon")) pcode_phon = pcode_x;
    }
  if (pcode_word != NULL) pcode1 = pcode_word;
  else
    {if (pcode_phon != NULL) pcode1 = pcode_phon;
     else fatal_error(proc,"Neither word- nor phone-level pcodeset defined.",999);
    }
/* for s/m logic to work, top-level pcode (pcode1) must be compositional */
  if (!pcode1->compositional)
     fatal_error(proc,"Top-level pcodeset is not compositional.",999);
  ttp_pcdrls_parms->desc = strdup_safe("Standard TTP3S Parameters",proc);
  if (streq(pcode1->element_type,"word"))
    {
/* get TTP parameters for making new words */
if (db_level > 0) printf("%s Reading in ttp pcdrls...\n",pdb);
    /* get ttp rules from ttp pcdrls file */
     make_pcd_from_rls_file(ttp_pcdrls,fname_ttp_pcdrls,path="",ttp_tgbound,perr);
     if (*perr > 0) fatal_error(proc,"make_pcd_from_rls_file fails",*perr);
     ttp_pcdrls_parms->pcdrls = ttp_pcdrls;
    /* get ttp back-off path */
     get_bpath_from_pcdrls1(ttp_bpath,ttp_pcdrls,ttp_tgbound,perr);
     if (*perr > 0) fatal_error(proc,"error return from get_bpath...",*perr);
if (db_level > 0) dump_bpaths(ttp_bpath);
     ttp_pcdrls_parms->bpath = ttp_bpath;
    /* get syllabification parameters */
     ttp_syl_parms->desc     = strdup_safe("Syllabification parameters.",proc);
     ttp_syl_parms->pcdp_dir = pcdtab->directory;
     ttp_syl_parms->data_dir = sylb_data_dir;
     ttp_syl_parms->pcdp     = pcode_phon;
if (db_level > 0) printf("%s Reading in syllabification parameters...\n",pdb);
     read_syl_parms(ttp_syl_parms,perr);
     if (*perr > 0) fatal_error(proc,"error return from read_in_syl_parms()",*perr);
     ttp_pcdrls_parms->syl_parms = ttp_syl_parms;

if (db_level > 0) dump_syl_parms(ttp_syl_parms);
    }
/* initialize score-keeping counters */
  nal_total = 0;
/* make alignment data objects */
  p1 = make_al_int_prot2("main/p1",pcode1);
  p2 = make_al_int_prot2("main/p2",pcode1);
  ps1 = make_al_chr_prot2("main/ps1");
 /* open alignment files */
  if (streq(fname_aln_in,"-")) fp_in = stdin;
  else
    {fp_in = fopen(fname_aln_in,"r");
     if (fp_in == NULL) fatal_error(proc,"Can't open fname_aln_in",999);
    }
  if (streq(fname_aln_out,"-")) fp_out = stdout;
  else
    {fp_out = fopen(fname_aln_out,"w");
     if (fp_out == NULL) fatal_error(proc,"Can't open fname_aln_out",999);
    }
if (db_level > 0) printf("%s Files opened.\n",pdb);
 /* and loop on contents */
if (db_level > 0) printf("%s Looping on contents.\n",pdb);
  at_end = F;
  while ((!at_end)&&(nal_total < lim))
    {get_next_alignment_chr_prot(fp_in,ps1,&at_end); /* read in next alignment */
     if (!at_end)
       {ps1->aligned = F;
        simplify_null_reps(ps1->sa->str);
        simplify_null_reps(ps1->sb->str);
        adjust_type_case(ps1->sa->str,pcode1);
        adjust_type_case(ps1->sb->str,pcode1);
        if (ntokens(ps1->sa->str) != ntokens(ps1->sb->str)) ps1->aligned = F;
        alignment_s_to_ir_prot(p1,ps1,pcode1,ttp_pcdrls_parms,perr);
        if (*perr > 0) fatal_error(proc,"alignment_s_to_ir_prot fails",*perr);
        remove_zeros(&(p1->nsa->str[0]));
        remove_zeros(&(p1->nsb->str[0]));
        p1->aligned = F;
        d=aldistsm_prot(p1,wod2_prot,return_alignment,fom_threshold,p2,perr); /* re-align it */
        if (*perr > 10) fatal_error(proc,"aldistsm fails",*perr);
if (db_level > 0) printf("%s Dph=%d, Err rate = %f\n",pdb,d,(double)d/(double)p1->nsa->str[0]);
        fprintf(fp_out,"\n");
        aln_i_to_s_prot5(p2,ps1,"|",perr);
        if (*perr > 0) fatal_error(proc,"aln_i_to_s_prot5 fails",*perr);
        fprintf(fp_out,"id: (%s)\n",ps1->id->str);
        fprintf(fp_out,"REF: %s\n",ps1->sa->str);
        fprintf(fp_out,"HYP: %s\n",ps1->sb->str);
        nal_total += 1;
      /* print out s/m's found if desired*/
        if ((print_sms)&&(p2->naux > 0))
          {if (!sm_header_printed)
             {fprintf(stdout,"# SPLIT/MERGES FOUND:\n");
              fprintf(stdout,"#      CASE I.D.   REF::HYP\n");
              sm_header_printed = T;
             }
           for (i=1; i <= p2->nsa->str[0]; i++)
             {ichr = p2->nsa->str[i];
              jchr = p2->nsb->str[i];
              if ((ichr > pcode1->pctab_length)
                ||(jchr > pcode1->pctab_length))
                {fprintf(stdout,"%16.16s  ",ps1->id->str);
                 fprintf(stdout," %s",ascii_stri_prot(nsx,ichr,pcode1,p2));
                 fprintf(stdout," :: ");
                 fprintf(stdout,"%s\n",ascii_stri_prot(nsx,jchr,pcode1,p2));
          }  }  }
	/* free auxtab in output alignment */
         for (i=1; i <= p2->naux; i++)
           {if (p2->auxtab[i] != NULL) destroy_prot_int_str(p2->auxtab[i]);
           }
         p2->naux = 0;
     }  }
   fprintf(stdout,"\n");
   fprintf(stdout," No. of alignments processed=%d\n",nal_total);
 /* free allocated memory */
   destroy_prot_chr_str(nsx);
   if (streq(pcode1->element_type,"word"))
     {free(ttp_pcdrls_parms->desc);
      free_pcode(ttp_pcdrls_parms->pcdrls);
      free_syl_parms2(ttp_syl_parms);
      free_bpath1(ttp_bpath);
     }
   free_code_table(pcdtab);
   free_al_int_prot(p1);
   free_al_int_prot(p2);
   free_al_chr_prot(ps1);
   return 0;
  } /* end main */

/******* CODE FOR FUNCTIONS USED, FOR EXPORT VERSION: ************************/
/* (you may uncomment these lines to include the code directly)              */
#include "./fcns/acstr_prot.c"
#include "./fcns/acstri_prot.c"
#include "./fcns/addpcd.c"
#include "./fcns/addstres_prot.c"
#include "./fcns/adjcase.c"
#include "./fcns/aldist2_prot.c"
#include "./fcns/aldistsm_prot.c"
#include "./fcns/aldistst_prot.c"
#include "./fcns/alitos2_prot.c"
#include "./fcns/alitos5_prot.c"
#include "./fcns/alstoi2r_prot.c"
#include "./fcns/aprules2_prot.c"
#include "./fcns/atobool.c"
#include "./fcns/boolpr1.c"
#include "./fcns/build_key3.c"
#include "./fcns/calloc2.c"
#include "./fcns/char_name_prot.c"
#include "./fcns/copintal_prot.c"
#include "./fcns/dauxtab_prot.c"
#include "./fcns/dbpaths.c"
#include "./fcns/dbpkg1.c"
#include "./fcns/dchral_prot.c"
#include "./fcns/dctable.c"
#include "./fcns/decode2.c"
#include "./fcns/decode3_prot.c"
#include "./fcns/del_eol.c"
#include "./fcns/dhpars1.c"
#include "./fcns/dintal2_prot.c"
#include "./fcns/dintal4_prot.c"
#include "./fcns/dpcode2.c"
#include "./fcns/dpcode3.c"
#include "./fcns/dppf2.c"
#include "./fcns/dpron2.c"
#include "./fcns/drules2.c"
#include "./fcns/dsylparms.c"
#include "./fcns/dwords1.c"
#include "./fcns/dsylbs1.c"
#include "./fcns/enclcs1r.c"
#include "./fcns/encode2r.c"
#include "./fcns/encode3r.c"
#include "./fcns/expenv.c"
#include "./fcns/fatalerr.c"
#include "./fcns/fbpath1.c"
#include "./fcns/fgets_prot.c"
#include "./fcns/find_key3.c"
#include "./fcns/fntoke1.c"
#include "./fcns/fntoke2.c"
#include "./fcns/fralchr_prot.c"
#include "./fcns/fralint_prot.c"
#include "./fcns/frctable.c"
#include "./fcns/frele.c"
#include "./fcns/frpcode.c"
#include "./fcns/frstr1.c"
#include "./fcns/frules2.c"
#include "./fcns/fsylparms2.c"
#include "./fcns/ftiers2.c"
#include "./fcns/gbpath1.c"
#include "./fcns/gcomflag.c"
#include "./fcns/gctable.c"
#include "./fcns/gpcaux.c"
#include "./fcns/gpcode3.c"
#include "./fcns/gppf2.c"
#include "./fcns/gnalc1_prot.c"
#include "./fcns/gnstrtab.c"
#include "./fcns/grules2.c"
#include "./fcns/hashfcn.c"
#include "./fcns/initaln2_prot.c"
#include "./fcns/initalc2_prot.c"
#include "./fcns/ipcdrls.c"
#include "./fcns/lc_istr_prot.c"
#include "./fcns/letfcns.c"
#include "./fcns/make_pcd_from_rls_file.c"
#include "./fcns/malchr_prot.c"
#include "./fcns/malint_prot.c"
#include "./fcns/malloc2.c"
#include "./fcns/mbalint_prot.c"
#include "./fcns/mfname1.c"
#include "./fcns/mkele1r.c"
#include "./fcns/mpron4.c"
#include "./fcns/mlower.c"
#include "./fcns/mupper.c"
#include "./fcns/no_wbndl.c"
#include "./fcns/no_wbndr.c"
#include "./fcns/nstrfcns.c"
#include "./fcns/ntokens.c"
#include "./fcns/okfcc2.c"
#include "./fcns/okicc2.c"
#include "./fcns/overlap1.c"
#include "./fcns/padwsp.c"
#include "./fcns/parse_rkey.c"
#include "./fcns/pchmeth1.c"
#include "./fcns/pcindex2r.c"
#include "./fcns/pcindex_bsearch.c"
#include "./fcns/pcindex5r.c"
#include "./fcns/pcsort1.c"
#include "./fcns/pick_min1du.c"
#include "./fcns/pltrim.c"
#include "./fcns/pltrimf.c"
#include "./fcns/prand2.c"
#include "./fcns/pronphon.c"
#include "./fcns/prot_str_fcns.c"
#include "./fcns/prot_nstr_fcns.c"
#include "./fcns/prtrim.c"
#include "./fcns/prtrim2.c"
#include "./fcns/rdiacrit.c"
#include "./fcns/remcomm.c"
#include "./fcns/remzeros.c"
#include "./fcns/repladd2.c"
#include "./fcns/rsylparms.c"
#include "./fcns/safepr1.c"
#include "./fcns/simpnull.c"
#include "./fcns/sm_pkg1pr.c"
#include "./fcns/spmode_prot.c"
#include "./fcns/sptiers2_prot.c"
#include "./fcns/ss_len.c"
#include "./fcns/ss_to_s.c"
#include "./fcns/sstok.c"
#include "./fcns/sstok2.c"
#include "./fcns/sstok4.c"
#include "./fcns/str_eq.c"
#include "./fcns/sstok_lr_s.c"
#include "./fcns/strcmpi.c"
#include "./fcns/strcutl.c"
#include "./fcns/strcutr.c"
#include "./fcns/strdup2.c"
#include "./fcns/strmap1.c"
#include "./fcns/strncmpi.c"
#include "./fcns/strseg.c"
#include "./fcns/swcase.c"
#include "./fcns/sylpreds.c"
#include "./fcns/textlen.c"
#include "./fcns/ttp_prep1_prot.c"
#include "./fcns/ttp3s_prot.c"
#include "./fcns/ttp_pcdrls2ss_prot.c"
#include "./fcns/valdata.c"
#include "./fcns/warn_add.c"
#include "./fcns/wbtrim.c"
#include "./fcns/wod2_prot.c"
#include "./fcns/zapchar.c"
