/* rc_file.cc */

#include "rc_file.h"
#include <LEDA/dictionary.h>
#include <fstream.h>
#include <ctype.h>

static const int npunc = 2;
static const char punc[npunc+1] = "#=";

static const char comment = '#';

struct rc_state {
  dictionary< string, list<string> *> vars;
  ~rc_state(void) {
    clear_rc();
  }
};

static rc_state rc;

bool is_punc( const char c ) {
  for( int i = 0 ; i < npunc ; i++ ) {
    if( c == punc[i] ) {
      return true;
    }
  }
  return false;
}

void parse_line( istream &str, list<string> &l ) {
  string s;
  s.read_line( str );

  int loc = 0, len = s.length();

  while( loc < len ) {
    while( isspace( s[loc] ) ) loc++;

    if( is_punc( s[loc] ) ) {
      if( s[loc] == comment ) return;
      l.append( s[loc++] );
    } else {
      int end = loc + 1;
      while( !isspace( s[end] ) && !is_punc( s[end] ) ) {
	end++;
      }
      l.append( s(loc, end-1 ) );
      loc = end;
    }
  }
}

bool load_rc( cstring filename ) {
  ifstream fstr( filename );
  
  if( !fstr ) return false;

  int ln = 0;
  while( 1 ) {
    list<string> line;
    
    do {
      parse_line( fstr, line );
      if( fstr.eof() ) {
	fstr.close();
	dc_trace( TRACE_MANY ) {
	  cerr << "\"" << filename << "\" : read " << ln << " lines\n";
	}
	return false;
      }
      ln++;
    } while( !line.length() );

    string varname = line.pop();
    if( line.length() && line.pop() != "=" ) {
      cerr << "\"" << filename << "\" : expected '=' at line " << ln << "\n";
      line.clear(); 
      return true;
    }
 
    list<string> *contents = new list<string>;
    contents->conc( line );
    rc.vars.insert( varname, contents );
  }
  return false;
}

void clear_rc( void ) {
  dic_item di;
  forall_items( di, rc.vars ) {
    delete( rc.vars.inf( di ) );
  }
  rc.vars.clear();
}

const list<string> *rc_get( cstring variable_name ) {
  dic_item di = rc.vars.lookup( variable_name );
  if( di == nil ) return nil;
  return rc.vars.inf( di );
}

bool rc_defined( cstring variable_name ) {
  return( rc.vars.lookup( variable_name ) != nil );
}

string rc_out( cstring variable_name ) {
  string out;
  const list<string > *vals = rc_get( variable_name );
  if( vals == nil ) return out;
  string s;
  forall( s, *vals ) {
    out += s + ' ';
  }
  return out;
}

ostream &print_rc( ostream &ostr = cout ) {
  dic_item di;
  forall_items( di, rc.vars ) {
    ostr << rc.vars.key( di );
    list<string> *vals = rc.vars.inf( di );
    if( vals->length() ) {
      ostr << " =";
      string s;
      forall( s, *vals ) {
	ostr << " \"" << s << "\"";
      }
    }
    ostr << "\n";
  }
  return ostr;
}
