#include "parserMem.h"
#include "functionMem.h"

#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iomanip>

using namespace std;

extern bool verbose;

#define REPORT if(verbose)cout << "Memory " << setw(30) << left << (mem->name + " : ") << i << "/" << maxAddr << setw(15) << " data defined." << endl;

/// Parse a memory file
bool ParserMem(string &filename){
	ifstream f(filename.c_str(),ios::in);

	if(verbose)cout << endl << "---------- Memory Parser ----------" << endl << endl;

	if(!f){
		cerr << "Memory parser ERROR : reading file." << endl;
		return 0;
	}

	string item;
	functionMem *mem=0;
	unsigned long i=0,val,maxAddr=0,maxVal=0;
	vector<functionMem *>::iterator it,it2;

	while(f>>item){
	    if(item.substr(0,4)=="mem:"){
	        it2 = it;
	        it = find_if(functionMem::listMems.begin(),functionMem::listMems.end(),FunctionMemSameName(item.substr(4)));
            if(it==functionMem::listMems.end()){
                cerr << "Memory parser ERROR : \"" << item << "\" doesn't exist." << endl;
                return false;
            }else{
                if(mem){
                    while(it2 = find_if(it2+1,functionMem::listMems.end(),FunctionMemSameName(mem->name)), it2!=functionMem::listMems.end()){
                        (*it2)->data = mem->data;
                    }
                    REPORT;
                }
                mem = *it;
                i=0;
                maxAddr = 1 << mem->addrLength;
                maxVal = (1 << mem->dataLength)-1;
            }
	    }else{
	        if(mem==0){
                cerr << "Memory parser ERROR : no memory selected" << endl;
                return false;
	        }
	        istringstream str(item);
	        if(!(str>>val)){
                cerr << "Memory parser ERROR : input format error - wait for a number" << endl;
                return false;
	        }
	        if(val>maxVal){
                cerr << "Memory parser ERROR : memory \"" << mem->name << "\" has only " << mem->dataLength << " data bits " << "(" << val << " is too big)." << endl;
                return false;
	        }
	        if(i<maxAddr){
	            mem->data[i]=val;
	            i++;
	        }else{
                cerr << "Memory parser ERROR : memory \"" << mem->name << "\" has only " << maxAddr << " data." << endl;
                return false;
	        }
	    }
	}
    if(mem){
        it2=it;
        while(it2 = find_if(it2+1,functionMem::listMems.end(),FunctionMemSameName(mem->name)), it2!=functionMem::listMems.end()){
            (*it2)->data = mem->data;
        }
        REPORT;
    }

	f.close();

	return true;
}
