#include "stdio.h"
#include "stdlib.h"
#include <string>
#include <iostream>
#include <fstream>


using namespace std;

///http://www.beyondttl.com/vcd.php

class myfile{
    public:
       myfile(string fname);
      char next();
       ~myfile();
    private:
       FILE *pFile;
       char cpuf;
       char counter;
       size_t result;
};
myfile::myfile(string fname){  
   pFile=fopen(fname.c_str(), "r"); 
   if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
   counter=0;}

char myfile::next(){  
   if (counter==0)
    {
     result= fread(&cpuf, 1,1, pFile);
     if (result <1) {exit (3);}
     counter=8;
     }
     counter--;
   return ((cpuf >> (counter)) & 0x1)+0x30;}  //30 or 31 for  ascii 0 or 1

myfile::~myfile(){
   fclose(pFile);}

//http://www.virtual-maxim.de/dynamische-datenstrukturen-%E2%80%93-einfach-verkettete-liste/

struct wire  {
      string name;
      char   reference;
      int    size;
      string value;  
      wire   *next;};

class wirelist
  {
    string timescale;
    wire element;
    wire *kopf;
    wire *ende;
    wire *current;
    char  nextreference;
    bool  timestamp;
    int   time;

    public:
    //Konstruktor
    wirelist(string t)
    {timescale=t;
     kopf = ende = NULL;
     nextreference='!';
     timestamp=false;
     time=0;}
     //Destruktor
 

    void addwire(string name, int size);
    void printheader(void);
    int datain(char in);
  };

int wirelist::datain(char in){
   static int size=0;
   static string inString;
   static int counter=0;

 

    if (current==NULL)
         {
           current=kopf;
           time++;
           timestamp=false;
         }
    inString=inString+in;
    size++;
   
    
    if (size==current->size)
      if (inString!=current->value)
        {  
           if (timestamp==false)
              {
               cout <<"#"<<time<<"\n";
               timestamp=true;
               
                if (in < 0x30) 
                  { 
                      return 0; // no new info end of conversion
                   }
              }
           cout <<"b" << inString <<" "<< current->reference<< "\n";
           size=0;
           current=current->next;
           inString.clear();
        }
    return 1;
    }

void wirelist::addwire(string name, int size){
    wire *neuerDraht= new wire();
    if (kopf==NULL)
        ende = kopf = current = neuerDraht;
    else
       {
        ende->next =neuerDraht;
        ende = neuerDraht;
       }
     neuerDraht->name.assign(name);
     neuerDraht->reference=nextreference++;
     neuerDraht->size=size;    
  };

void wirelist::printheader(void){
       wire *a=kopf;   
     
       cout <<"$timescale "<< timescale <<" fs $end\n";
       cout << "$module logic $end\n";
       while (a)
         {cout <<"$var reg "<< a->size<<" "<< a->reference << " "<< a->name <<" $end\n";
          a=a->next;}
       cout<<"$upscope  $end\n";
       cout<<"$end definitions $end\n";
       }



int main(int argc, char *argv[])
{  ifstream config;
   string fstr;
   int    fint;


   config.open(argv[2]); 

 

  getline(config,fstr);

  wirelist kabelbaum(fstr);

  while (config >> fint >> fstr)
    {
      kabelbaum.addwire(fstr,fint);      
     }
   config.close();


   kabelbaum.printheader();


  
   myfile redfile(argv[1]);
   int i;
 

  
  
      
   while (   kabelbaum.datain(redfile.next()))
     {}

 

}




