#include "translate.h"

// globale variables
int I,T;                      // I: image sizem, T: template size
int nst,sst,pst;              // indices for number, symbol, parentheses stacks
int numstk[10],symstk[10];    // number & symbol stacks
char var[MAX_VAR_NUM][MAX_LENGTH_NAME];    // table for var name
int val[MAX_VAR_NUM];                      // table for var value 
int varnum=0;                              // index for var tables

// function prototypes  
void scanASM(istream&);
void scanBVC(istream&);
char nextchar(istream&);
int expr(istream&);
void ASC_ASM(istream&);
void ASM_BVC(const char[MAX_LENGTH_INSTRLINE],int);
void lookuptbl(char[MAX_LENGTH_NAME], int);
void setTypeNo(const char[MAX_LENGTH_NAME],const char[MAX_LENGTH_NAME],int&);
void readstr(istream&, char[MAX_LENGTH_NAME]);
void SyntErr();
void Expr_err();

void scanASC(istream& istrm)     // scan ASC file
{
  char next_char;
  char ch;

  next_char=0;
  next_char=nextchar(istrm);

  while (eof[0]==0) {
    switch(next_char) {
    case '{':                    // deal with { 
      ASCBrace[++ascbrc]=Nasc+1;
      ch=istrm.get();
      next_char=nextchar(istrm);
      break;
    case '}':                     // deal with }
      int b,e,loop,i,j,k;
      ch=istrm.get();
      b=ASCBrace[ascbrc--];
      next_char=nextchar(istrm);
      if (next_char=='*'){
	istrm>>ch;
	e=Nasc;
	nst=0;sst=0;pst=0;
	loop=expr(istrm);        // evaluate nested loop repetition factor
	for(i=1;i<loop;i++) {    // replicate ASCs from b to e for loop times
	  for (j=b;j<=e;j++) {
	    int p;
	    Nasc++;
	    ASCcall[Nasc]=ASCcall[j];
	    ASMcall[Nasc]=ASMcall[j];
	    BVCcall[Nasc]=BVCcall[j];
	    p=0;
	    while (ASCcall[Nasc][p]!=' '){
	      asc[Nasc][p]=ASCcall[Nasc][p];
	      p++;
	    }
	    asc[Nasc][p]='\0';
	    for (k=1;k<=TPN;k++){   // replicate Dat array
	      if (Dat[k][1][j]>0)
		Dat[k][1][Nasc]=Dat[k][1][j];
	      if (Dat[k][2][j]>0)
		Dat[k][2][Nasc]=Dat[k][2][j];
	      if (Dat[k][3][j]>0)
		Dat[k][3][Nasc]=Dat[k][3][j];
	    }
	  }  
	}
	next_char=nextchar(istrm);
      }
      break;
    case ',':                      // deal with , 
      ch=istrm.get();
      next_char=nextchar(istrm);
      break;
    default: 
      // deal with ASC call
      ASC_ASM(istrm); 
      next_char=nextchar(istrm);
    }
    if (next_char==EOF) eof[0]=1; // end of ASC file
  }
}

void scanASM(istream& istrm)      // scan ASM opcode in translation table
{
  char next_char;
  char ch;

  next_char=0;
  next_char=nextchar(istrm);

  while (eof[1]==0) {
    switch(next_char) {
    case '{':                     // deal with { 
      ASMBrace[++asmbrc]=asmi+1;
      ch=istrm.get();
      next_char=nextchar(istrm);
      break;
    case '}':                     // deal with } 
      int b,e,loop,i,j;
      ch=istrm.get();
      b=ASMBrace[asmbrc--];
      next_char=nextchar(istrm);
      if (next_char=='*'){
	istrm>>ch;
	e=asmi;
	nst=0;sst=0;pst=0;
	loop=expr(istrm);        // evaluate nested loop repetition factor
	for(i=1;i<loop;i++) {    // replicate ASMs from b to e for loop times
	  for (j=b;j<=e;j++) {
	    asmi++;
	    Trn[asctp].callNop[asmi]= Trn[asctp].callNop[j];
	    Trn[asctp].calls[asmi]=(char*)malloc((strlen(Trn[asctp].calls[j])+1)*sizeof(char));
	    strcpy(Trn[asctp].calls[asmi], Trn[asctp].calls[j]);
	  }  
	}

	if (asmi==Trn[asctp].callNo) eof[1]=1;  // end of ASM opcode sequence
	next_char=nextchar(istrm);
      }
      break;
    case ',':                                   // deal with , 
      ch=istrm.get();
      next_char=nextchar(istrm);
      break;
    default: 
      // set ASM in Trn table
      char temp[MAX_LENGTH_NAME];  
      int t,l;
      ::memset(temp, 0, MAX_LENGTH_NAME);
      asmi++;
      istrm>>temp;
      istrm>>t;
      l=strlen(temp);
      Trn[asctp].callNop[asmi]=t;
      Trn[asctp].calls[asmi]=(char*)malloc((l+1)*sizeof(char));
      strcpy(Trn[asctp].calls[asmi],temp);
      if (asmi==Trn[asctp].callNo) eof[1]=1;    // end of ASM opcode sequence
      next_char=nextchar(istrm);
    }
  }
}

void scanBVC(istream& istrm)
{
  char next_char;
  char ch;

  next_char=0;
  next_char=nextchar(istrm);

  while (eof[2]==0) {
    switch(next_char) {
    case '{':                     // deal with {
      BVCBrace[++bvcbrc]=bvci+1;
      ch=istrm.get();
      next_char=nextchar(istrm);
      break;
    case '}':                     // deal with } 
      int b,e,loop,i,j;
      ch=istrm.get();
      b=BVCBrace[bvcbrc--];
      next_char=nextchar(istrm);
      if (next_char=='*'){
	istrm>>ch;
	e=bvci;
	nst=0;sst=0;pst=0;
	loop=expr(istrm);        // evaluate nested loop repetition factor
	for(i=1;i<loop;i++) {    // replicate BVCs from b to e for loop times
	  for (j=b;j<=e;j++) {
	    bvci++;
	    Trn[asmtp].callNop[bvci]= Trn[asmtp].callNop[j];
	    Trn[asmtp].calls[bvci]=(char*)malloc((strlen(Trn[asmtp].calls[j])+1)*sizeof(char));
	    strcpy(Trn[asmtp].calls[bvci], Trn[asmtp].calls[j]);
	  }  
	}
	if (bvci==Trn[asmtp].callNo) eof[2]=1;  // end of BVC opcode sequence
	next_char=nextchar(istrm);
      }
      break;
    case ',':                                   // deal with ,  
      ch=istrm.get();
      next_char=nextchar(istrm);
      break;
    default: 
      // set BVC list in Trn table
      char temp[MAX_LENGTH_NAME]; 
      int t,l;
      ::memset(temp, 0, MAX_LENGTH_NAME);
      bvci++;
      istrm>>temp;
      istrm>>t;
      l=strlen(temp);
      Trn[asmtp].callNop[bvci]=t;
      Trn[asmtp].calls[bvci]=(char*)malloc((l+1)*sizeof(char));
      strcpy(Trn[asmtp].calls[bvci],temp);
      if (bvci==Trn[asmtp].callNo) eof[2]=1;
      next_char=nextchar(istrm);
    }
  }
}
char nextchar(istream& istrm)   // get the next meaningful char from stream
{
  char temp[MAX_LENGTH_LINE];
  char next_char;
  char ch;
  int e;
  next_char = istrm.peek();
  do {
    while (next_char=='\t' || next_char==' ') {   // ignore tab and space
      ch=istrm.get();
      next_char = istrm.peek();
    }
    e=0;
    while (next_char=='#'||next_char=='\n') {     // ignore comment and '\n' 
      istrm.getline(temp,MAX_LENGTH_LINE);
      next_char=istrm.peek();
      e=1;
    }
  }while(e==1);
  return next_char;
}

int comptmd(int i)                 // compute * , / and \ in expression
{
  if (symstk[sst-1]=='*') {
    sst--;nst--; 
    return numstk[nst]*i;
  }
  else if (symstk[sst-1]=='/') {
    sst--;nst--; 
    return numstk[nst]/i;
  }
  else if (symstk[sst-1]=='\\') {  // \ is the ceiling of /
    int q;
    sst--;nst--; 
    q=numstk[nst]/i;
    if (q*i<numstk[nst]) return q+1;
    else return q;
  }
  else return i;
}
void comptas()                    // compute + and - in expression
{
  if (symstk[sst-1]=='+') {
    sst--;nst--; 
    numstk[nst-1]=numstk[nst-1]+numstk[nst];
  }
  else if (symstk[sst-1]=='-') {
    sst--;nst--; 
    numstk[nst-1]=numstk[nst-1]-numstk[nst];
  }
}
int expr(istream& istrm)          // compute expression
{
  char next_char;
  char ch;
  char varname[MAX_LENGTH_NAME];
  int varval;
  int loop,i;
  if (istrm.peek()==10) next_char=10;
  else next_char=nextchar(istrm);
  if (next_char<='9' && next_char >='0') {  // deal with number
    istrm>>i;
    i=comptmd(i);
    numstk[nst]=i;
    nst++;
    loop=expr(istrm);
  }
  else if ((next_char>'A'&&next_char<'Z')||(next_char>'a'&&next_char<'z')) {
                                            // deal with char
    int vi=0;
    do{                                     // get var name
      istrm>>ch;
      varname[vi++]=ch;
      ch=istrm.peek();
    }while (ch!='\n'&&ch!=' '&&ch!='\t'&&ch!='('&&ch!=')'&&ch!='{'&&ch!='}'
	    &&ch!='+'&&ch!='-'&&ch!='*'&&ch!='/'&&ch!='\\'&&ch!=',');
    varname[vi]='\0';
    if (strcmp(varname,"I")==0)      i=comptmd(I);      // I: image size
    else if (strcmp(varname,"T")==0)   i=comptmd(T);    // T: template size
    else if (strcmp(varname,"MESH")==0) i=comptmd(MESH);// MESH: mesh size
    else {                                              // regular variable
      for (int j=1;j<=varnum;j++) {    // look up var value in name-value table
	if (strcmp(var[j],varname)==0){
	  varval=val[j];
	  break;
	}
      }
      i=comptmd(varval);
    }
    numstk[nst]=i;
    nst++;
    loop=expr(istrm);
  }
  else if (next_char=='+') {
    istrm>>ch;
    comptas();
    symstk[sst]='+';
    sst++;
    loop=expr(istrm);
  }
  else if (next_char=='-') {
    istrm>>ch;
    comptas();
    symstk[sst]='-';
    sst++;
    if (nst==0) {
      numstk[0]=0;
      nst++;
    }
    loop=expr(istrm);
  }
  else if (next_char=='*') {
    istrm>>ch;
    symstk[sst]='*';
    sst++;
    loop=expr(istrm);
  }
  else if (next_char=='/') {
    istrm>>ch;
    symstk[sst]='/';
    sst++;
    loop=expr(istrm);
  }
  else if (next_char=='\\') {
    istrm>>ch;
    symstk[sst]='\\';
    sst++;
    loop=expr(istrm);
  }
  else if (next_char=='(') {
    istrm>>ch;
    symstk[sst]='(';
    sst++;pst++;
    loop=expr(istrm);
  }
  else if (next_char==')'&&pst>0) {
    istrm>>ch;
    comptas();
    sst--;nst--;pst--;
    i=comptmd(numstk[nst]);
    numstk[nst]=i;
    nst++;
    loop=expr(istrm);
  }
  else {
    comptas();
    if (nst==1 && sst==0) loop = numstk[0];   // end of expression
    else Expr_err();
  }
  return loop;
}

void ASC_ASM(istream& istrm)    // parse ASC call and translate ASC to ASM
{
    char tp[MAX_LENGTH_NAME];
    int input_size[2],resbits,rs[3],pim,tsize;
    char ch;

	istrm>>ASC.opcode;                  // get opcode

	// set varibles
	if ((strcmp(ASC.opcode, "MOCSET")==0)         // MOCSET
	    ||(strcmp(ASC.opcode, "MOCSETMESH")==0)){ // MOCSETMESH 
	  do {
	    int vi=0;
	    varnum++;
	    // get variable name
	    ch=nextchar(istrm);
	    if (ch<'A'||ch>'z'||(ch>'Z'&&ch<'a')) SyntErr();
	    istrm>>ch;
	    while (ch!=' '&&ch!='\t'&&ch!='='){
	      var[varnum][vi++]=ch;
	      istrm>>ch;
	    }
	    var[varnum][vi]='\0';

	    // expect "="
	    if (ch!='=') { 
	      ch=nextchar(istrm);
	      istrm>>ch;
	    }
	    if (ch!='=') SyntErr();

	    istrm>>val[varnum];                // get variable value
	    if (strcmp(ASC.opcode, "MOCSETMESH")==0)
	      MESH*=val[varnum];
	    ch=istrm.peek();
	    if (ch==' '||ch=='\t'||ch==',') {
	      if (ch!=',') ch=nextchar(istrm);
	      istrm>>ch;
	    }
	  }while (ch==',');             // end of assignment to one variable
	  return;                       // done MOCSET
	}
	  
	// parse ASC call
	Nasc++;                             // increase # of ASC calls
	ostrstream ostrasc(ASCcall[Nasc],MAX_LENGTH_LINE);
	strcpy(asc[Nasc],ASC.opcode);

	istrm>>ch;                          // expect "("
	if (ch!='(') SyntErr();
	ostrasc<<ASC.opcode<<" (";

	for(int i=0;i<2;i++) {

	  nst=0;sst=0;pst=0;
	  ASC.D[i]=expr(istrm);             // get D1,D2
	  ostrasc<<ASC.D[i]<<",";
	  nextchar(istrm);istrm>>ch;        // expect ","
	  if (ch!=',') SyntErr();
	  input_size[i]=1;
	  for(int j=1;j<=max(ASC.D[0],ASC.D[i]);j++) {       
	    nst=0;sst=0;pst=0;
	    ASC.Md[i][j]=expr(istrm);       // get M11,...,M1D1,M21,...,M2D2
	    nextchar(istrm);istrm>>ch;      // expect ","
	    if (ch!=',') SyntErr();
	    input_size[i]*=ASC.Md[i][j];    // compute input size
	    ostrasc<<ASC.Md[i][j]<<",";
	  }
	  if (i==0) {
	    pim=input_size[i];
	    I=pim;                          // compute image size
	  }
	  else T=input_size[i];             // compute template size
	  
	  nst=0;sst=0;pst=0;
	  ASC.Sig[i]=expr(istrm);          // get S1,S2
	  nextchar(istrm);istrm>>ch;       // expect ","
	  if (ch!=',') SyntErr();
	  input_size[i]*=ASC.Sig[i];       // compute input size
	  nst=0;sst=0;pst=0;
	  ASC.Noi[i]=expr(istrm);          // get N1,N2
	  nextchar(istrm);istrm>>ch;       // expect ","
	  if (ch!=',') SyntErr();
	  ostrasc<<ASC.Sig[i]<<","<<ASC.Noi[i]<<",";

	  for(int j=1;j<=max(ASC.D[0],ASC.D[i]);j++) {
	    nst=0;sst=0;pst=0;
	    ASC.T[i][j]=expr(istrm);         // get T11,...,T1D1,T21,...,T2D2
	    nextchar(istrm);istrm>>ch;       // expect ","
	    if (ch!=',') SyntErr();
	    ostrasc<<ASC.T[i][j]<<",";
	  }
	  ostrasc<<" ";
	}

	readstr(istrm,ASC.r);               // get r
	nst=0;sst=0;pst=0;
	ASC.Pr=expr(istrm);                 // get Pr
	nextchar(istrm);istrm>>ch;          // expect ","
	if (ch!=',') SyntErr();
	readstr(istrm,ASC.o);               // get o
	nst=0;sst=0;pst=0;
	ASC.Po=expr(istrm);                 // get Po
	ostrasc<<ASC.r<<","<<ASC.Pr<<","<<ASC.o<<","<<ASC.Po;
	nextchar(istrm);istrm>>ch;          // expect ")"
	if (ch!=')') SyntErr();
	ostrasc<<")"<<ends;

	type(ASC.opcode,tp,asctp);           // get type of opcode if it exists
	if (asctp==-1) lookuptbl(ASC.opcode,1);
                            // lookup translation table if opcode doesn't exist

	// calculate # of input, instruction bits
	Dat[asctp][1][Nasc] = input_size[0]+input_size[1];
	Ins[asctp][1] = 8+(10+ASC.D[0]*2+ASC.D[1]*2)*16;

	//  calculate # of result bits from ASC
	resbits = max(ASC.Pr,ASC.Po)*pim;
	/*
	if ((strcmp(ASC.r,"-1")==0)&&(strcmp(ASC.o,"-1")!=0))
	  resbits = ASC.Po*pim;                 // case 1. Pointwise
	else if ((strcmp(ASC.r,"-1")!=0)&&(strcmp(ASC.o,"-1")==0))
	  resbits = ASC.Pr*pim;                 // case 2. Global reduce
	else if ((strcmp(ASC.r,"+")==0)||(strcmp(ASC.r,"max")==0)||(strcmp(ASC.r,"min")==0))
	  if (strcmp(ASC.o,".")==0)
	    resbits = max(ASC.Pr,ASC.Po)*pim;
	  else if (strcmp(ASC.o,"+")==0)
	    resbits = max(ASC.Pr,ASC.Po)*pim;
	  else SyntErr();
	else SyntErr();
	*/

	// compute ASM register size
	// Case 2: global reduce operations
	if ((strcmp(ASC.r,"-1")!=0)&&(strcmp(ASC.o,"-1")==0)) {
	  rs[0]=ASC.Sig[0]*pim;
	  rs[1]=0;
	  rs[2]=ASC.Pr*pim;
	  /*
	  if ((strcmp(ASC.r,"max")==0)||(strcmp(ASC.r,"min")==0))
	    rs[2]=ASC.Sig[0];
	  else if (strcmp(ASC.r,"+")==0)
	    rs[2]=ASC.Sig[0]+(int)(log(pim)/log(2)+1);
	  else if (strcmp(ASC.r,"x")==0)
	    rs[2]=ASC.Sig[0]*(int)(log(pim)/log(2)+1);
	  else rs[2]=ASC.Pr;
	  */
	}

	// Case 1,3,4
	else 
	  if (ASC.D[1]==0) {
	    rs[0]=ASC.Sig[0]*pim;
	    rs[1]=0;
	    rs[2]=resbits;
	  }
	  else {
	    rs[0]=rs[1]=max(ASC.Sig[0],ASC.Sig[1])*pim;
	    rs[2]=resbits;
	  }


	// build list of ASM calls 
	Nasm=0;
	ASMcall[Nasc]=(char**)malloc((Trn[asctp].callNo+1)*sizeof(char*));
	BVCcall[Nasc]=(char***)malloc((Trn[asctp].callNo+1)*sizeof(char**));
	for(int i=1;i<=Trn[asctp].callNo;i++) {
	  char temp[MAX_LENGTH_INSTRLINE];
	  ostrstream ostrasm(temp,MAX_LENGTH_INSTRLINE);
	  ostrasm<<Trn[asctp].calls[i];
	  for(int j=0;j<Trn[asctp].callNop[i];j++)
	    ostrasm<<" R"<<j+1<<" "<<rs[j];
	  ostrasm<<ends;
	  ASMcall[Nasc][++Nasm]=(char*)malloc((strlen(temp)+1)*sizeof(char)); 
	  strcpy(ASMcall[Nasc][Nasm],temp);

	  ASM_BVC(ASMcall[Nasc][Nasm],Trn[asctp].callNop[i]);
	                               // all ASM_BVC() to translate ASM to BVC
	}
	return;
}

void ASM_BVC(const char ASMline[MAX_LENGTH_INSTRLINE],int nop)
                                              // translate ASM to BVC
{

    int q, ncyc;
    char tp[MAX_LENGTH_NAME];
    int resbits;
    int rs[3];
    char ch;


      // get ASM line parameters

	istrstream istrasm(ASMline);
	ASM.regsize1=0;                       // initialize
	ASM.regsize2=0;
	ASM.regsize3=0;

	istrasm>>ASM.opcode;                  // get op name
	if (nop>0) {
	  istrasm>>ASM.regid1;                // get reg-id1
	  istrasm>>ASM.regsize1;              // get reg-size1
	  if (nop>1) {
	    istrasm>>ASM.regid2;              // get reg-id2
	    istrasm>>ASM.regsize2;            // get reg-size2
	    if (nop>2) {
	      istrasm>>ASM.regid3;            // get reg-id3
	      istrasm>>ASM.regsize3;          // get reg-size3
	    }
	  }
	}

	type(ASM.opcode,tp,asmtp);           // get type of opcode if it exists
	if (asmtp==-1) lookuptbl(ASM.opcode,2);
                            // lookup translation table if opcode doesn't exist

	// copmute data, result, and instruction bits
	Dat[asmtp][1][Nasc] = ASM.regsize1+ASM.regsize2;
	resbits = ASM.regsize3;
	Ins[asmtp][1] = 116;

	// compute reg sizes for BVC
	rs[0]=0;
	rs[1]=0;
	rs[2]=0;
	if (nop>0) {
	  rs[0]=ASC.Sig[0];
	  rs[1]=ASC.Sig[1];
	  if (strcmp(ASC.o,"x")==0) rs[2]=rs[0]+rs[1];
	  else if (strcmp(ASC.o,"+")==0) rs[2]=1+max(rs[0],rs[1]);
	  else rs[2]=max(rs[0]+rs[1],1+max(rs[0],rs[1]));
	}

	// build the list of BVC calls
	Nbvc=0;
	BVCcall[Nasc][Nasm]=(char**)malloc((Trn[asmtp].callNo+1)*sizeof(char[MAX_LENGTH_INSTRLINE]));
	for(int i=1;i<=Trn[asmtp].callNo;i++) {
	  char temp[MAX_LENGTH_INSTRLINE];
	  ostrstream ostrbvc(temp,MAX_LENGTH_INSTRLINE);
	  ostrbvc<<Trn[asmtp].calls[i];
	  for(int j=0;j<Trn[asmtp].callNop[i];j++)
	    ostrbvc<<" R"<<j+1<<" "<<rs[j];
	  ostrbvc<<ends;
	  BVCcall[Nasc][Nasm][++Nbvc]=(char*)malloc((strlen(temp)+1)*sizeof(char)); 
	  strcpy(BVCcall[Nasc][Nasm][Nbvc],temp);

	  type(Trn[asmtp].calls[i],tp,bvctp);// get type of opcode if it exists
	  if (bvctp==-1) 
	    setTypeNo(Trn[asmtp].calls[i],Trn[asmtp].calls[i],bvctp);
                            // lookup translation table if opcode doesn't exist

	  // set Trn, Dat, Ins arrays
	  Trn[bvctp].Ncyc = 1;
	  Trn[bvctp].callNo = 0;
	  Dat[bvctp][1][Nasc] = rs[0]+rs[1];
	  Ins[bvctp][1] = 38;
	  Dat[bvctp][2][Nasc] = rs[0]+rs[1]+rs[2];
	  Ins[bvctp][2] = 38;
	  Dat[bvctp][3][Nasc] = rs[2];

	}

  return ;

}


void lookuptbl(char opcode[MAX_LENGTH_NAME],int mb)	  
                         // lookup the translation table file  
{
    char tp[MAX_LENGTH_NAME];
    int tpno;
    char ch;

  // look up opcode in SIMD-MOC-trn.tbl 
	  ifstream trntbl("SIMD_MOC_trn.tbl"); // open SIMD_MOC_trn.tbl file
	  if (!trntbl) {
	    cout<<"Cannot open SIMD_MOC_trn.tbl file.\n";
	    exit(-1);
	  }

	  char temp[MAX_LENGTH_LINE],nch;
	  int found=0;
	  nch=trntbl.peek();
	  do {
	    if ((nch!=' ')&&(nch!='\t')&&(nch!='\n')&&(nch!='#')&&(nch!=0)) {

	      // look up opcode by comparing opcode with 1st word in a line
	      char opc[MAX_LENGTH_NAME];
	      ::memset(opc, 0, MAX_LENGTH_NAME);
	      trntbl>>opc;
	      if (strcmp(opc,opcode)==0) {
		int n, ncyc;
		found=1;
		trntbl>>ch;
		trntbl>>ch;
		nst=0;sst=0;pst=0;
		n=expr(trntbl);          // get n, # of opcodes translated into
		nextchar(trntbl);trntbl>>ch;
		if (ch!=',') SyntErr();
		nst=0;sst=0;pst=0;
		ncyc=expr(trntbl);                 // get Ncyc
		nextchar(trntbl);trntbl>>ch;
		if (ch!=',') SyntErr();
		trntbl>>tp;                        // get type of opcode

		// set Trn table values
		setTypeNo(opcode,tp,tpno);
		Trn[tpno].Ncyc = ncyc;
		Trn[tpno].callNo = n;
		Trn[tpno].callNop=(int*)malloc((n+1)*sizeof(int));
		Trn[tpno].calls=(char**)malloc((n+1)*sizeof(char*));

		eof[mb]=0;
		if (mb==1)                         // for ASM 
		  { asmi=0; asctp=tpno;asmbrc=0;scanASM(trntbl);}
		else                               // for BVC 
		  { bvci=0; asmtp=tpno;bvcbrc=0;scanBVC(trntbl);}

	      } //end of if (strcmp(opc,opcode)==0)
	    } //end of if ((nch!=' ')&&(nch!='\t')&&(nch!='#')&&(nch!=0))

	    if (found==0) {                        // go to next line
	      trntbl.getline(temp, MAX_LENGTH_LINE); 
	      nch=trntbl.peek();
	    }
	  } while (found==0 && nch!=EOF);
	  
	  trntbl.close();

	  if (found==0) {                          // not found
	    cout<<ASC.opcode<<"cannot be found in SIMD_MOC_trn.tbl file.\n";
	    exit(-1);
	  }
}


void type(const char opcode[MAX_LENGTH_NAME],char tp[MAX_LENGTH_NAME],int& tpn)
                                                  // get the type of an opcode
{
  tpn=-1;
  for(int i=1;i<=TPN;i++)
    if (strcmp(opcode,typehtbl[i][0])==0) {
      strcpy(tp,typehtbl[i][1]);
      tpn=i;
    }
}

void setTypeNo(const char opcode[MAX_LENGTH_NAME],const char tp[MAX_LENGTH_NAME],int& tpn)                                       // set the type of an opcode
{
  TPN++;
  strcpy(typehtbl[TPN][0],opcode);
  strcpy(typehtbl[TPN][1],tp);
  tpn=TPN;
}


void readstr(istream& istrm, char s[MAX_LENGTH_NAME])
                                              // read opcode from line stream
{
  int i=0;
  char ch;
  ::memset(s, 0, MAX_LENGTH_NAME);

  istrm>>ch;
  while (ch!=',') {
    s[i++]=ch;
    istrm>>ch;
    if (i>=MAX_LENGTH_NAME-1) SyntErr();
  }
  if (i==0) SyntErr();
  s[i]='\0';
}

void SyntErr()                 // syntax error
{
  cout<<"Syntax Error!"<<endl;
  exit(-1);
}
void Expr_err()                // error in expression
{
  cout<<"Error in expression!"<<endl;
  exit(-1);
}


main(int argc, char *argv[])
{
  extern void Host(const char[][MAX_LENGTH_NAME],const int);

  ifstream in(argv[1]);                // open asc file, argv[1]: asc file name
  if (!in) {
    cout << "Cannot open ASC file.\n";
    return 1;
  }
  char str[MAX_LENGTH_NAME],str1[MAX_LENGTH_NAME];
  int m1,m2,t;

  scanASC(in);             // call scanASC() to translate
  in.close();

  Host(asc,Nasc);                // call Host() in moc to compute time
  return 0;

}

