/* Note for input file format:

should declare first V,then A, then T all grouped by type
 
 */
#include <stdio.h>
#include <stdlib.h>

#define FLISTNAME "PRH_ParamHandler_INFN_auto.id"
#define TRUE 1 
#define FALSE 0
#define MAXMODE 2

#define SETPARAMETERGEN 0x20
#define TESTDEBUG 0x43

struct list_el
{
  struct list_el *next;
  char string[255];
  int id;
}; 

typedef struct 
{
  char str[255];
  unsigned char code;
} sub_struct;

typedef struct list_el listItem;


listItem *beginList,*beginCommand=NULL; 
unsigned char bufferOut[2048];
int subid;
sub_struct subCommandMode[MAXMODE]={{"SetParameterGen",SETPARAMETERGEN},{"TestDebug",TESTDEBUG}};


void convertHex2Dec(char *str)
{
  char tmp[255]="";
  char dec[10]="";
  char *p,*s;
  unsigned int value;

  if ((p = strstr(str,"0x")) != NULL)
    {
      strncat(tmp,str,p-str);
      sscanf(p+2,"%x",&value);
      sprintf(dec,"%d",value);
      strcat(tmp,dec);
      memcpy(str,tmp,strlen(tmp));
      str[strlen(tmp)]=0;
     }
}

int loadList(char * filename,listItem **first,int command)
{
  FILE *fileList;
  char *s;
  char tmp[255],tmp_1[255];

  int ret = TRUE;

  listItem *loc=NULL,*cur;

  if ((fileList = fopen(filename,"r")) != NULL)
    {
      while (fgets(tmp,254,fileList) != NULL )
	 {
	   cur = (listItem*)malloc(sizeof(listItem));

	   if (loc == NULL)
	     {
	       *first = cur; loc = cur;
	       cur->next = NULL;
	     }
	   else
	     {
	       loc->next = cur;
	       loc = cur;
	       cur->next = NULL;
	     }
	   
	   if (command == TRUE)
	     {
	       strncpy(cur->string,tmp,strlen(tmp)-1);
	     }
	   else
	     {
	       sscanf(tmp,"%s %d\n",tmp_1,&ret);
	       strncpy(cur->string,tmp_1,strlen(tmp_1));
	     }
	   cur->id = ret;
	 }
      ret = TRUE;
      fclose(fileList);
    }
  else
    {
      printf("Cannot open file %s!!!\n",FLISTNAME);
      ret = FALSE;
    }

  return(ret);
}

void parseCommand()
{
  listItem *loc;
  char fileName[255];
  int count = 0;
  int VCount = 0,VFirst = TRUE,VSave,VInc;
  int ACount = 0,AFirst = TRUE,ASave,AInc;
  int TCount = 0,TFirst = TRUE,TSave,TInc;

  loc = beginCommand;
  memset(bufferOut,0,2048);

  while (loc != NULL)
    {
      if (count == 0)
	{
	  if ((loc->string[0] == 0x0a) || (loc->string[0] == 0x0))
	    {
	      printf("Finished !");
	      exit(0);
	    }
	  
	  strncpy(fileName,loc->string,strlen(loc->string)+1);
	  loc = loc->next;
	  count++;

	  if (strcmp(loc->string,""))
	    printf("Processing file: %s\n",fileName);
	  
	  continue;
	}
      
      if (count == 1)
	{
	  if ((subid = returnID(loc->string)) != -1)
	    {
	      bufferOut[0] = 0;
	      bufferOut[1] = subid;
	      loc = loc->next;
	      count+=3;
	      continue;
	    }
	  else 
	    {
	      printf("Fatal Error: unknown subcommand %s\n",loc->string);
	      exit(1);
	    }
	}
      
      if (strcmp(loc->string,""))
	printf("Processing: %s \n",loc->string); 

      convertHex2Dec(loc->string);
      
      switch (subid)           // last subid
	{
	case SETPARAMETERGEN :
	  
	  switch (loc->string[0])
	    {
	    case 'V'  :
	      {
		char type[255],name[255];
		unsigned int value,id;
		
		sscanf(loc->string,"%s %s %d\n",type,name,&value);
		
		if (VFirst)
		  {
		    VSave = count;   // the place for the command number 
		    VFirst = FALSE;
		    VInc = 1;        // do not consider N after first time 
		  }
		
		if ((id = scanList4ID(name)) != -1)
		  {
		    bufferOut[count+VInc] = id;
		    bufferOut[count+1+VInc] = ((value & 0xff000000) >> 24);
		    bufferOut[count+2+VInc] = ((value & 0x00ff0000) >> 16);
		    bufferOut[count+3+VInc] = ((value & 0x0000ff00) >> 8);
		    bufferOut[count+4+VInc] = value & 0x000000ff;
		    
		    count+=(5+VInc);
		    VCount++;
		    VInc = 0;
		  }
		else 
		  {
		    printf("Fatal Error: unknown macrocommand %s\n",loc->string);
		    exit(1);
		  }
		
		if (loc->next)
		  if (loc->next->string[0] != loc->string[0])
		    bufferOut[VSave] = VCount;
	      }
	      break;
	      
	    case 'A' : 
	      {
		char type[255],name[255];
		unsigned int value,id,index;
		
		if (VFirst)                      // write 0 if V is not present
		  {
		    bufferOut[count] = 0;
		    count++;
		    VFirst = 0;
		  }
		
		sscanf(loc->string,"%s %s %d %d\n",type,name,&index,&value);
		
		if (AFirst)
		  {
		    ASave = count;   // the place for the command number 
		    AFirst = FALSE;
		    AInc = 1;
		  }
		
		if ((id = scanList4ID(name)) != -1)
		  {
		    bufferOut[count+AInc] = id;
		    bufferOut[count+1+AInc] = index;
		    bufferOut[count+2+AInc] = ((value & 0xff000000) >> 24);
		    bufferOut[count+3+AInc] = ((value & 0x00ff0000) >> 16);
		    bufferOut[count+4+AInc] = ((value & 0x0000ff00) >> 8);
		    bufferOut[count+5+AInc] = value & 0x000000ff;
		    count+=(6+AInc);
		    ACount++;
		    AInc = 0;
		  }
		else 
		  {
		    printf("Fatal Error: unknown macrocommand %s\n",loc->string);
		    exit(1);
		  }
		
		if (loc->next)
		  if (loc->next->string[0] != loc->string[0])
		    bufferOut[ASave] = ACount;
	      }
	      break;
	      
	    case 'T'  :
	      {
		char type[255],name[255];
		unsigned int value,id,row,col;
		
		sscanf(loc->string,"%s %s %d %d %d\n",type,name,&row,&col,&value);
		
		if (VFirst)                      // write 0 if V is not present
		  {

		    bufferOut[count] = 0;
		    count++;
		    VFirst = 0;
		  }
		
		if (AFirst)                      // write 0 if V is not present
		  {
		    bufferOut[count] = 0;
		    count++;
		    AFirst = 0;
		  }
		
		if (TFirst)
		  {
		    TSave = count;   // the place for the command number 
		    TFirst = FALSE;
		    TInc = 1;
		  }
		
		if ((id = scanList4ID(name)) != -1)
		  {
		    bufferOut[count+TInc] = id;
		    bufferOut[count+1+TInc] = row;
		    bufferOut[count+2+TInc] = col;
		    bufferOut[count+3+TInc] = ((value & 0xff000000) >> 24);
		    bufferOut[count+4+TInc] = ((value & 0x00ff0000) >> 16);
		    bufferOut[count+5+TInc] = ((value & 0x0000ff00) >> 8);
		    bufferOut[count+6+TInc] = value & 0x000000ff;
		    
		    count+=(7+TInc);
		    TCount++;
		    TInc = 0;
		  }
		else 
		  {
		    printf("Fatal Error: unknown macrocommand %s\n",loc->string);
		    exit(1);
		  }
		
		if (loc->next)
		  if (loc->next->string[0] != loc->string[0])
		    bufferOut[TSave] = TCount;
	      }
	      break; 
	    case 0    : 
	      {
		int c;
		
		if (VFirst)                      // write 0 if V is not present
		  {
		    bufferOut[count] = 0;
		    count++;
		  }
		
		if (AFirst)                      // write 0 if V is not present
		  {
		    bufferOut[count] = 0;
		    count++;
		  }
		
		if (TFirst)                      // write 0 if V is not present
		  {
		    bufferOut[count] = 0;
		    count++;
		  }
		
		c = count;
		
		while ((count % 4) != 0)
		  count++;
		
		memset(&bufferOut[c],0,count-c);
		
		bufferOut[2] = (((count-4)/4) & 0x0100) >> 8;
		bufferOut[3] = ((count-4)/4) & 0x00ff;	    
		
		if (!write2File(fileName,count))
		  {
		    printf("Error writing on file %s\n",fileName);
		    exit(1);
		  }
		
		count = 0;
		VCount = 0; VFirst = TRUE;
		ACount = 0; AFirst = TRUE;
		TCount = 0; TFirst = TRUE;
	      }
	      break;
	      
	    default  : 
	      printf("Fatal Error : variable identifier not known !\n");
	      exit(1);
	    }
	  break;

	case TESTDEBUG:
	  {
	    unsigned int value;

	    if (loc->string[0])
	      {
		sscanf(loc->string,"%d\n",&value);
				
		bufferOut[count] = ((value & 0xff00) >> 8);
		bufferOut[count+1] = value & 0x00ff;
		count+=2;
	      }
	    else
	      {
		bufferOut[2] = 0;
		bufferOut[3] = 1;
		
		if (!write2File(fileName,count))
		  {
		    printf("Error writing on file %s\n",fileName);
		    exit(1);
		  }
		
		count = 0;
	      }
	    
	  }
	  break;
	}
      
      loc = loc->next;
      
    }
}

int returnID(char *key)
{
  int i;

  for (i=0; i < MAXMODE; i++)
    {
      if (strncmp(key,subCommandMode[i].str,strlen(subCommandMode[i].str)) == 0)
	  return subCommandMode[i].code; 
    }
  return(-1);
}

int scanList4ID(char *name)
{
  listItem *loc;

  loc = beginList;
  
  while (loc != NULL)
    {
      if (strncmp(name,loc->string,strlen(loc->string)) == 0)
	return loc->id;
      loc = loc->next;
    }
  return(-1);
}


int write2File(char *filename,int count)
{
  FILE *out;
  int ret = TRUE;
  int i = 0,c;
  char binname[255];
  unsigned short data;

  c = count;

  if ((out = fopen(filename,"w")) != NULL)
    {
      count = count / 2;
      
      while (count--)
	{
      	  fprintf(out,"0x%02x%02x\n",bufferOut[i],bufferOut[i+1]);
	  i+=2;
	}
      fclose(out);
    }
  else 
    ret = FALSE;
  
  
  strcpy(binname,filename);
  strcat(binname,".bin");
  
  if ((out = fopen(binname,"w")) != NULL)
    {
      c = c / 2; i = 0;
      
      while (c--)
	{
	  data = *(unsigned short*)&bufferOut[i];
      	  fputc((unsigned char)((data & 0xff00) >>  8),out);
      	  fputc((unsigned char)((data & 0x00ff)),out);
	  i+=2;
	}
      
      fclose(out);
    }
  else 
    ret = FALSE;
  
  return(ret);
}

void printList(listItem *first)
{
  listItem *loc;
  
  loc = first;

  while (loc != NULL)
    {
      printf("%s %d\n",loc->string,loc->id);
      loc = loc->next;
    }
}
int main (int argc,char *argv[])
{
  if (argc > 1)
    {
      loadList(FLISTNAME,&beginList,FALSE);
      loadList(argv[1],&beginCommand,TRUE);

      printf("Processing file %s\n\n",argv[1]);
      
      parseCommand();
    }
  else
    printf("\nMissing filename !!\n");
  return 0;
}


