// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// readdata.cc --- class readdata functions
// -----
// ChangeLog:
// 2007. 11. 21
//  Redirected log messages to l_file.
// -----

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cstdarg>
#include <iostream>

using std :: cerr ;
using std :: endl ;


#include "readdata.hh"

// データファイルアクセスエラー
void
readdata :: err_access
()
{
  cerr << "Error: data file access denied" << endl ;
  exit ( 30 ) ;
}


// データファイルアクセスエラー
void
readdata :: err_access
( char * s )
{
  cerr << "Error: data file " << s << " access denied" << endl ;
  exit ( 30 ) ;
}


// データファイルエラー
void
readdata :: err_eof
()
{
  cerr << "Error: data file not correct" << endl ;
  exit ( 34 ) ;
}


// データファイルエラー
void
readdata :: err_eof
( char * s )
{
  cerr << "Error: data file " << s << " not correct" << endl ;
  exit ( 34 ) ;
}



// データファイルエラー
void
readdata :: err_eof
( bool & sw ,
  char * s )
{
  if ( sw ) err_eof( s ) ;
  sw = true ;
}



// コメント行検出, sw = false で eof 検出 OK
int
readdata :: comm_out
( FILE * fl ,
  bool sw /* = true */ )
{
    char c ;
    if ( (c = fgetc(fl)) == EOF ) {
	if ( sw ) err_eof() ;
	else return EOF ;
    }
  SHARP:
    if ( c == '#' ) {				// # を発見したら
	while ( c != '\n' ) {			// 行末まで空読み
	    if ( (c = fgetc(fl)) == EOF ) {		// 漢字code大丈夫?
		if ( sw ) err_eof() ;
		else return EOF ;
	    }
	}
	if ( (c = fgetc(fl)) == EOF ) {		// \nの次１字読む
	    if ( sw ) err_eof() ;
	    else return EOF ;
	}
    } else if ( ! isspace(c) ) goto ENDING ;	// スペース以外では終了
    while ( isspace(c) ) {              	// スペースも読み飛ばす
	if ( (c = fgetc(fl)) == EOF ) {
	    if ( sw ) err_eof() ;
	    else return EOF ;
	}
    }

// # 発見したら戻る
//  BACK:	// -Wall warning: label defined but not used 回避
    if (c == '#') goto SHARP ;

// 終了
  ENDING:
    ungetc(c, fl) ;				// c を押し戻す
    return c ;
}

// コマンド名を得る
int readdata::getcommand
(FILE* fl, bool sw /* = true */) {
    if ( comm_out(fl, sw) == EOF ) return EOF ;	// コメントアウト
    if ( fscanf(fl, "%s ", tmpch) == EOF ) {	// 読み込む
	if ( sw ) err_eof() ;
	else return EOF ;
    }
    return 1 ;
}

// コマンド名を得る
int readdata::getcommand
(FILE* fl, char* flname) {
    if ( comm_out(fl, true) == EOF ) err_eof(flname) ;
    if ( fscanf(fl, "%s ", tmpch) == EOF )		// 読み込む
	err_eof(flname) ;
    return 1 ;
}

// コマンド名( enum )を得る
commandvalue readdata::getcommandvalue
( FILE* fl, char* flname ) {
    if ( comm_out( fl, true ) == EOF ) {
        err_eof( flname ) ;
    }
    if ( fscanf( fl, "%s ", tmpch ) == EOF ) {		// 読み込む
	err_eof( flname ) ;
    }

    commandlist a ;
    a.cmdname = tmpch ;
    char* bs_result ;
    bs_result = (char*) bsearch
        ( ( char* ) ( &a ), ( char* ) comlist, comnum,
          sizeof( commandlist ), sortcommands ) ;
    if ( bs_result == NULL ) {
        return END_OF_DATA ;
    } else {
        return ( ( commandlist* ) bs_result ) -> cmdval ;
    }
}

// コマンド名( enum )を得る
void readdata::getcommandvalue
( FILE* fl, char* flname, commandvalue com_req ) {
    commandvalue com_get = getcommandvalue( fl, flname ) ;
    if ( com_get != com_req ) {
        err_eof( flname ) ;
    }
}

int readdata::getdouble
(FILE* fl, char* fls, double& dbl) {		// 倍精度実数型変数を得る
    if ( getdouble(fl, dbl) == EOF ) err_eof(fls) ;
    return 1 ;
}

// 倍精度実数型変数を得る
int readdata::getdouble
(FILE* fl, double& dbl) {
    if ( comm_out(fl, false) == EOF ) return EOF ;
    if ( fscanf(fl, "%s ", tmpch) == EOF ) return EOF ;
    sscanf(tmpch, "%lf ", &dbl) ;
    return 1 ;
}

// 倍精度実数型変数を二つ得る
int readdata::gettwodbls
(FILE* fl, char* fls, double& dbl, double& dbl2) {
    if ( gettwodbls(fl, dbl, dbl2) == EOF ) err_eof(fls) ;
    return 1 ;
}

// 倍精度実数型変数を二つ得る
int readdata::gettwodbls
(FILE* fl, double& dbl, double& dbl2) {
    if ( getdouble(fl, dbl) == EOF ) return EOF ;
    if ( getdouble(fl, dbl2) == EOF ) return EOF ;
    return 1 ;
}

// 倍精度実数型変数を三つ得る
int readdata::getthreedbls
(FILE* fl, char* fls, double& dbl,
 double& dbl2, double& dbl3) {
    if ( getthreedbls(fl, dbl, dbl2, dbl3) == EOF ) err_eof(fls) ;
    return 1 ;
}

// 倍精度実数型変数を三つ得る
int readdata::getthreedbls
(FILE* fl, double& dbl,
 double& dbl2, double& dbl3) {
    if ( gettwodbls(fl, dbl, dbl2) == EOF ) return EOF ;
    if ( getdouble(fl, dbl3) == EOF ) return EOF ;
    return 1 ;
}

// 整数型変数を得る
int readdata::getint
(FILE* fl, char* fls, int& dbl) {
    if ( getint(fl, dbl) == EOF ) err_eof(fls) ;
    return 1 ;
}

// 整数型変数を得る
int readdata::getint
(FILE* fl, int& dbl) {
    if ( comm_out(fl, false) == EOF ) return EOF ;
    if ( fscanf(fl, "%s ", tmpch) == EOF ) return EOF ;
    sscanf(tmpch, "%d ", &dbl) ;
    return 1 ;
}

void readdata::setsw(bool& sw) {
    if (sw) err_eof() ;
    sw = true ;
}

// 整数型変数を二つ得る
int readdata::gettwoints
(FILE* fl, char* fls, int& itx, int& ity) {
    if ( gettwoints(fl, itx, ity) == EOF ) err_eof(fls) ;
    return 1 ;
}

// 整数型変数を二つ得る
int readdata::gettwoints
(FILE* fl, int& itx, int& ity) {
    if ( getint(fl, itx) == EOF ) return EOF ;
    if ( getint(fl, ity) == EOF ) return EOF ;
    return 1 ;
}

// コマンドを比較
bool readdata::cmpcommand
(char* cmd) {
    if ( strcmp(tmpch, cmd) == 0 ) return true ;
    else return false ;
}

// コマンドを比較
bool readdata::cmpcommand
(char* cmd, char* fls) {
    if ( strcmp(tmpch, cmd) != 0 ) err_eof(fls) ;
    else return true ;
    return false ;	// -Wall warning 回避
}

// コマンドを比較
bool readdata::cmpcommand
(FILE* fl, char* cmd, char* fls, bool sw /* = false */) {
    getcommand(fl, fls) ;
    if ( strcmp(tmpch, cmd) != 0 ) {
	if (sw) return false ;
	else err_eof(fls) ;
    } else return true ;
    return false ;	// -Wall warning 回避のため
}
