/* This C++ program converts strings like 'abcd0x23' to 'abcd{****x23}' and
'abcd0I' to 'abcd{***x0}' in a SPIDER batch file. 

To compile on SGI, type

       CC -o convert convert.C 
       CC -o32 -mips2 -o convert convert.C 

To run, type 

       convert inputfilename outputfilename

 author: Yu Chen   Nov.1,1999 */

#include <stdio.h>
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

const int MAX=160;
char result[MAX];

void clear(char*);
int location(char*,int,char*);
void convert(char*,char*,char*);

class stack {
public: int top;
        char st[MAX];
        char result[MAX];

        stack()
        {
	  top=0;
	}

        void push(char c)
        {
          st[top]=c;
          top++;
        }
        
        char pop()
        {
	  return(st[--top]);
	}

        void clear()
        {
	  for (int j=0;j<=MAX;j++)
	    st[j]='\0';
	  j=0;
	  top=0;
	}

        char* popall()
        {
	  int stacklen=strlen(st);
	  while(top>0){
	    result[stacklen-top-1]=st[--top];
	  }
	  result[stacklen]='\0';
	  top=0;
	  stacklen=0;
	  clear();

	  return(result);
	}
};

void rever(char tobe[])
{
  int tobelength=0;
  int ruler=0;
 
  tobelength =strlen(tobe);
  ruler=tobelength;
  clear(result);

  while(ruler>=0){
    result[tobelength-ruler-1]=tobe[ruler];
    ruler--;  
}

  ruler=0;
  tobelength=0;
}

void clear(char str[])
{ 
 for (int j=0;j<=MAX;j++)
   str[j]='\0';
 j=0;
}

int location(char daughter[],int len,char mother[])
{
  int length;
  
  if((strlen(mother))>=(strlen(daughter))){
    length=strspn(mother,daughter);
  }
  if (length==len){
    return 1;
  } else{
    return 0;
  }
}

void convert(char input[], char output[], char goodput[])
{

  char input0[MAX];
  char comment[MAX];
  char leading[MAX],trailing[MAX];

  int w=0;
  int i=0,j=0,length=0,number=20;

  struct pair {
    char name[10];
    int  len;};

  pair keywords[]={{"else",4},{"endif",5},{"en",2},{"end",3},{"RE",2},{"md",2},{"me",2},{"sta",2},{"tron",4},{"troff",5},{"opon",4},{"opoff",5},{"vbon",4},{"vb0ff",5},{"mosaicon",8},{"mosaicoff",9},{"inlnbuff",8},{"setmp",5},{"setmem",6},{"noresults",9}};
 
  clear(output); 
  clear(goodput);
  clear(comment);
  clear(leading);
  clear(trailing);


  strcpy(input0,input);  


  // tell apart the statement and comment
  if (strstr(input,";")!=NULL){      
    i=0;
    while(input[i]!=';'){
      goodput[i]=input[i];
      i++;
    }
    goodput[i]='\0';
    j=0;
    while(input[i]!='\0'){
      comment[j]=input[i];
      i++;j++;
    }
    comment[j]='\0';

    strcpy(input,goodput);
  }
  else{
    strcpy(comment,"");
  } // comment kept in "comment[]" and good part in "goodput".


  //eleminating leading spaces
  i=0; j=0;
  while (isspace(input[i])){
    leading[i]=' ';
    i++;
  }
  leading[i]='\0';
  while (input[i]!='\0'){
    goodput[j]=input[i];
    i++;j++;
  }
  goodput[j]='\0';




  //eleminating trailing spaces
  strcpy(input,goodput);
  clear(goodput);

  length=strlen(input);
  int indice = length -1;

  while (isspace(input[indice])){
      trailing[length-1-indice]=' ';
      input[indice]='\0';
      indice--;
  }
  trailing[length-1-indice]='\0';
  input[indice+1]='\0';
  strcpy(goodput,input);




  // ignoring lines with spaces. 
  if (strstr(goodput," ")!=NULL){      
      strcpy(output,input0);
      return;
  }



  // eleminating spaces in between
  strcpy(input,goodput);
  clear(goodput);
  j=0;
  for(i=0;i<=strlen(input);i++){
    if (!isspace(input[i])) {
      goodput[j]=input[i];
      j++;
    }
  }
  goodput[j]='\0';




  // ignoring lines with symbols, and keywords. ********************
  switch(goodput[0]){
  case ';': case '<': case '[': case '@': case '_': case '(': case '-':
  case '0': case '1': case '2': 
  case '3': case '4': case '5': 
  case '6': case '7': case '8': case '9': 
    
    strcpy(output,input0);
    return;

  default:
    if ((strstr(goodput,"=")!=NULL)||(strstr(goodput,",")!=NULL)||(strstr(goodput,"-")!=NULL)){
      strcpy(output,input0);
      return;
    }

    int m=0,flag=0;
    while(m<number){
      if((location(keywords[m].name,keywords[m].len,goodput))&&(strlen(goodput)==keywords[m].len)){

	  flag=1;
	  break;
      }else{
	  m++;
      }
    }
    if(flag==1){
      strcpy(output,input0);
      return;
    }
    break;
} // end switch 





  // ignoring linew begin with if(, lb and gotolb 
  if(strlen(goodput)>=3){
    if((location("lb",2,goodput))&&(isdigit(goodput[2]))){
      strcpy(output,input0);
      return;
    } else if ((location("if",2,goodput))&&((goodput[2])=='(')){
      strcpy(output,input0);
      return;
    }
  }

  if(strlen(goodput)>=7){
    if((location("gotolb",6,goodput))&&(isdigit(goodput[6]))){
      strcpy(output,input0);
      return;
    }
  }
  // end of if(,lb and gotolb.





  // **********************************************
  // ****************  starts here  ***************
  // **********************************************

  int current = strlen(goodput)-1;
  int state=0;  // 0:other, 1: digit,    2:'x', 3:'0'
  int flag=0;   // 0:other, 1:'A'..'Z',  2:'0'
  int redlight=0; 
  char tail;
  stack smstack, lgstack;

  while(current>=0){

    if (isdigit(goodput[current])){

    do {
        if((state==0)&&(isdigit(goodput[current]))){
          state=1;
          smstack.push(goodput[current]);
          current--;
        }
        else if ((state==1)&&(isdigit(goodput[current]))){
	  smstack.push(goodput[current]);
	  current--;
	} 
	else if((state==1)&&(tolower(goodput[current])=='x')){
	  state=2;
	  smstack.push(goodput[current]);
	  smstack.push('*');
	  smstack.push('*');
	  smstack.push('*');
	  current--;
	}
	else if ((state==2)&&(goodput[current]=='0')){
	  state=3;
	  smstack.push('*');
	  current--;
	}
	else if (state==2){
	  state=0;
	  smstack.push('{');
	  lgstack.push('}');

	  w = smstack.top;
	  while(w>0){
	    lgstack.push(smstack.st[smstack.top-w]);
	    w--;
	  }
	  smstack.clear();
	  lgstack.push(goodput[current]);
	  current--;
	}

	else if ((state==3)&&(goodput[current]=='0')){
	  smstack.push('*');
	  current--;
	}

	else if (state==3){
	  state=0;
	  smstack.push('{');
	  lgstack.push('}');

	  w = smstack.top;
	  while(w>0){
	    lgstack.push(smstack.st[smstack.top-w]);
	    w--;
	  }
	  smstack.clear();
	  lgstack.push(goodput[current]);	  
	  current--;
	}

	else if(state==1){
	  state=0;
	  w = smstack.top;
	  while(w>0){
	    lgstack.push(smstack.st[smstack.top-w]);
	    w--;
	  }
	  smstack.clear();
	  lgstack.push(goodput[current]);
      	  current--;
       	}

	else{
	  w=0;
	  lgstack.push(goodput[current]);
	  current--;
	}
      } while (current>=0);

      state = 0;
      smstack.top-=3;
      w=smstack.top;
      while(w>0){
	lgstack.push(smstack.st[smstack.top-w]);
	w--;
      }
      smstack.clear();
      lgstack.push(goodput[current]);

    } // end if (end with digits)


 
   if(isalpha(goodput[current])){
	flag = 1;
	smstack.push('0');
	smstack.push('x');
	smstack.push('*');
	smstack.push('*');
	current--;

	do {
	  if((flag==1)&&((goodput[current]=='0')||(goodput[current]=='*'))){
	    flag=2;
	    redlight=1;
	    tail=goodput[current];
	    smstack.push('*');
	    smstack.push('{');
	    current--;
	  }

	  else if((redlight==1)&&(flag==2)&&(goodput[current]==tail)){
	    //    smstack.push('*');
	    redlight=0;
	    current--;
	  }
	  else if((redlight==0)&&(flag==2)&&(goodput[current]==tail)){
	    smstack.push(goodput[current]);
	    current--;
	  }

	  else if (flag==2){
	    flag=0;
	    //	    smstack.push('{');
	    lgstack.push('}');

	    w = smstack.top;
	    while(w>0){
	      lgstack.push(smstack.st[smstack.top-w]);
	      w--;
	    }
	    smstack.clear();

	    lgstack.push(goodput[current]);
	    current--;
	  }

	  else if(flag==1){
	    flag=0;

	    smstack.clear();
	    lgstack.push(goodput[current+1]);
	    lgstack.push(goodput[current]);
	    current--;
	  }

	  else{
	    lgstack.push(goodput[current]);
	    current--;
	  }
	} while (current>=0);

      smstack.clear();
      }   // end if (end with letter)

  else {  // >=2 but neither end with digit nor letter.

   if ( goodput[current]=='}'){

     do { 
       lgstack.push(goodput[current]);
       current--;
     } while (goodput[current]!='{');

   }

     lgstack.push(goodput[current]);
     current--;
   }
  
  } //end while >=2

  rever(lgstack.st);
  strcat(leading,result);
  strcat(leading,trailing);
  strcpy(output,leading);
  strcat(output,comment);
  lgstack.clear();

} //end function

void main(int argc, char** argv)
{   
   char buffer[MAX],buffer1[MAX],buffer2[MAX];
   char *batchin, *batchout;
 
   if (argc <3){
     printf("\nNo input or output file name, please try again. \n\n");
     exit(0);
   }

   batchin = argv[1];
   batchout = argv[2];

   ifstream infile(batchin,ios::in);
   ofstream outfile( batchout,ios::out );

   do {
     infile.getline(buffer, 200);
     convert(buffer,buffer1,buffer2);
     outfile<<buffer1<<endl;
   } while ( infile.peek() != EOF);
   
   infile.close();
   outfile.close();
   }











