
/*
 *
 * UNICON - The Console Chinese & I18N
 * Copyright (c) 1999-2002
 *
 * This file is part of UNICON, a console Chinese & I18N
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * See the file COPYING directory of this archive
 * Author: see CREDITS
 */

#include <stdio.h>
#include <stdarg.h> 
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include "xl_hzinput.h"
#include "xl_sysphrase.h"
#include "xl_phrase.h"

FILE *fr, *fw;
int lineno;

void print_error(char *fmt,...)
{
    va_list args;

    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    fprintf(stderr,"\n");
    exit(-1);
}

char *skip_space(char *s)
{
    while ((*s==' ' || *s=='\t') && *s) s++;
    return s;
}

char *to_space(char *s)
{
    while (*s!=' ' && *s!='\t' && *s) s++;
    return s;
}

void del_nl_space(char *s)
{
    char *t;

    int len = strlen (s);
    if (!*s) 
        return;
    t = s + len - 1;
    while ((*t=='\n' || *t==' ' || *t=='\t') && s<t) 
        t--;
    *(t+1)=0;
}


void get_line(u_char *tt)
{
    while (! feof(fr)) 
    {
        fgets (tt, 128, fr);
    lineno++;
        if (tt[0] == '#') 
            continue;
        else  
            break;
    }
}

void cmd_arg(u_char *s, u_char **cmd, u_char **arg)
{
    char *t;

    get_line(s);
    if (!*s) { *cmd=*arg=s; return; }

    s=skip_space(s);
    t=to_space(s);
    *cmd=s;
    if (!(*t)) {
    	*arg=t;
    	return;
    }
    *t=0;
    t++;
    t=skip_space(t);
    del_nl_space(t);
    *arg=t;
}

#define MAXSIZE            100000
/* maximum char/phrase can be defined */

ITEM            ItemOut[MAXSIZE];
AssociatePhrase MyPhraseItem[MAXSIZE];
static char *TL_SYSPHRASE_FILE = "tl_sysphrase.bin";
static TL_SysPhrase_T *pDefaultSysphrase = NULL;

int main (int argc, char **argv)
{
    int i,k;
    char fname[64], fname_cin[64], fname_tab[64];
    char fname_phr[64],fname_lx[64];
    char tt[128];
    u_char *cmd, *arg;
    hz_input_table InpTable;
    int TotalKeyNum;
    int TotalAssociatePhrase = 0;
    ITEM LastItem;
    int index,ItemCount;
    u_short CharDef[64];
    int phrase_count=0, phrasebuf_pointer=0;
    u_long freq; 
    long nPhrase;
    int  opt, build_sysphrase = 1;
    char *sysdumpfilename = NULL;
    extern char *optarg;
    extern int optind;

    if (argc<=1) 
    {
        printf ("%s [-o <SysPhrase File>] -c <file.cin> \
                    [-d <sysfile dumpname][-n] \n", argv[0]);
        printf ("      -n -- no sysphrase output\n");
//        printf("Enter table file name [.cin] : ");
//        scanf("%s", fname);
        exit (0);
    }

#define ACCEPTOPTS      "no:c:d:"
    while ((opt = getopt(argc, argv, ACCEPTOPTS)) != -1) 
    {
#undef ACCEPTOPTS
        switch (opt) 
        {
            case 'o':
                TL_SYSPHRASE_FILE = optarg;
                break;
            case 'c':
                strcpy (fname, optarg);
                break; 
            case 'd':
                sysdumpfilename = optarg;
                break;
            case 'n':
                build_sysphrase = 0;
                break;
            default:
                printf ("Error in Parameter \n");
                exit (0);
        } 

    }
    pDefaultSysphrase = LoadSystemPhrase (TL_SYSPHRASE_FILE, 0);
    if (sysdumpfilename != NULL)
    {
        TL_DumpAllPhrase (pDefaultSysphrase, sysdumpfilename);
        exit (0);
    }
    sprintf (fname_cin, "%s.cin", fname);
    sprintf (fname_tab, "%s.tab", fname);
    if ((fr = fopen(fname_cin, "r")) == NULL ) 
        print_error("Cannot open %s \n", fname_cin);
    //pDefaultSysphrase = LoadSystemPhrase (TL_SYSPHRASE_FILE, 0);
    bzero(&InpTable,sizeof(InpTable));
    bzero(ItemOut,sizeof(ItemOut));
    bzero(MyPhraseItem, sizeof (MyPhraseItem));
    InpTable.item = ItemOut;
    InpTable.pAssociatePhrase = MyPhraseItem;

    printf("Generating binary *.tab file for input method %s...\n",fname_cin);

    /************** Now some basic information ************************/
    strcpy(InpTable.magic_number,MAGIC_NUMBER);
    cmd_arg(tt, &cmd, &arg);
    if (strcmp(cmd,"%ename") || !(*arg) )
        print_error("%d:  %%ename english_name  expected", lineno);
    arg[CIN_ENAME_LENGTH-1]=0;
    strcpy(InpTable.ename,arg);

    cmd_arg(tt, &cmd, &arg);
    if (strcmp(cmd,"%prompt") || !(*arg) )
        print_error("%d:  %%prompt prompt_name  expected", lineno);
    arg [CIN_CNAME_LENGTH-1]=0;
    strcpy(InpTable.cname, arg);

    cmd_arg(tt,&cmd, &arg); 
    if (strcmp(cmd,"%selkey") || !(*arg) )
        print_error("%d:  %%selkey select_key_list expected", lineno);
    strcpy(InpTable.selkey,arg);

    cmd_arg(tt,&cmd, &arg);
    if (strcmp(cmd,"%last_full") || !(*arg)) 
        InpTable.last_full = 1;
    else 
    {
        if (arg[0] == '0') 
            InpTable.last_full=0;
        else 
            InpTable.last_full=1;
        cmd_arg(tt, &cmd, &arg);
    }

    if (strcmp(cmd,"%dupsel") || !(*arg) )
        print_error("%d:  %%dupsel NO of dup sel keys  expected", lineno);
    InpTable.MaxDupSel=atoi(arg);

    /*************** now the keyname ****************************/

    cmd_arg(tt,&cmd, &arg);
    if (strcmp(cmd,"%keyname") || strcmp(arg,"begin"))
        print_error("%d:  %%keyname begin   expected", lineno);

    TotalKeyNum=0;
    while(1) 
    {
        cmd_arg(tt,&cmd, &arg);
        if (!strcmp(cmd,"%keyname")) break;
        k = tolower(cmd[0]);  /* k = char */
        if (InpTable.KeyMap[k]) 
            print_error("%d:  key %c is already used",lineno, k);

        InpTable.KeyMap[k] = ++TotalKeyNum;

        if (TotalKeyNum > 63)
            print_error("Error, at most 64 key can be defined!\n");
        InpTable.KeyName[TotalKeyNum] = arg[0];
    }

    InpTable.KeyMap[32] = 0;  /* SPACE = 32 */
    InpTable.KeyName[0] = ' ';
    TotalKeyNum++;
    InpTable.TotalKey = TotalKeyNum;    /* include space */

    /****************** now the character/phrase ***********************/
    //cmd_arg(tt,&cmd, &arg);
    index=0;
    TotalAssociatePhrase = 0;
    while (!feof(fr)) 
    {
        int len, k, m, n;
        u_long key1,key2;

        cmd_arg(tt,&cmd,&arg);
        if (!cmd[0] || !arg[0]) 
            break;
        len = strlen(cmd);
        if (len > InpTable.MaxPress) 
            InpTable.MaxPress=len;
        if (len > 10) 
            print_error("%d:  only <= 10 keys is allowed",lineno);

        key1 = key2=0;
        for (i = 0;i < len; i++) 
        {
    	    if (i < 5) 
            {
    		k = InpTable.KeyMap[cmd[i]];
    		key1 |= k << (24-i*6);
    	    }
    	    else 
            {
    		k = InpTable.KeyMap[cmd[i]];
    		key2 |= k<< (24-(i-5)*6);
    	    }
        }
        memcpy(&InpTable.item[index].key1, &key1, 4);
        memcpy(&InpTable.item[index].key2, &key2, 4);

        if (TL_MatchPhrase (pDefaultSysphrase, arg, &freq, &nPhrase) == 0)
        {
            nPhrase = TL_AppendPhrase (pDefaultSysphrase, arg);
            TL_GetPhraseFreq (pDefaultSysphrase, nPhrase, &freq);
        }
        InpTable.item[index].nPhrase = nPhrase;
        // InpTable.item[index].frequency = freq;

        m = (*arg) * 256 + *(arg+1);
        if (InpTable.pAssociatePhrase[m].total == 0)
        {
            InpTable.pAssociatePhrase[m].pPhrase = 
                        (ITEM **) malloc (sizeof (ITEM *) * 5);
            TotalAssociatePhrase ++;
        }
        else if (InpTable.pAssociatePhrase[m].total % 5 == 0)
        {
            int total = InpTable.pAssociatePhrase[m].total + 5;
            ITEM **q = InpTable.pAssociatePhrase[m].pPhrase;
            q = (ITEM **) realloc (q, sizeof (ITEM *) * total);
            InpTable.pAssociatePhrase[m].pPhrase = q; 
        }
        n = InpTable.pAssociatePhrase[m].total;
        InpTable.pAssociatePhrase[m].pPhrase[n] = 
                                            &InpTable.item[index];
        InpTable.pAssociatePhrase[m].total ++;
        index++;
    }
    fclose(fr);

    InpTable.TotalChar = index;
    InpTable.TotalAssociatePhrase = TotalAssociatePhrase;
    SortPhraseItem (pDefaultSysphrase, &InpTable);
   /**************** generate 64 index number ***********************/
    bzero (CharDef, sizeof(CharDef));
    for (i = 0; i < index; i++) 
    {
        int kk = InpTable.item[i].key1 >> 24 & 0x3f; 
        if (!CharDef[kk]) 
        {
            InpTable.KeyIndex[kk]= (unsigned int) i; 
            CharDef[kk]=1;
        }
    }

    InpTable.KeyIndex[TotalKeyNum] = index;
    for(i=TotalKeyNum-1; i>0; i--)
    {
        if (!CharDef[i]) 
            InpTable.KeyIndex[i] = InpTable.KeyIndex[i+1];
    }
    SaveLoadInputMethod (&InpTable, fname_tab);

    if (build_sysphrase == 1)
        TL_SaveAllPhrase (pDefaultSysphrase, TL_SYSPHRASE_FILE);
    return 0;
}

