// 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 const * 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 const * s )
{
  cerr << "Error: data file " << s << " not correct" << endl ;
  exit ( 34 ) ;
}



// データファイルエラー
void
readdata :: err_eof
( bool & sw ,
  char const * 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 const * 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 const * 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 const * bs_result ;
  bs_result
    = ( char const * ) bsearch
    ( ( char const * ) ( & a ) , ( char const * ) 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 const * flname ,
  commandvalue com_req )
{
  commandvalue com_get = getcommandvalue ( fl , flname ) ;
  if ( com_get != com_req )
  {
    err_eof ( flname ) ;
  }
}



// 倍精度実数型変数を得る
int
readdata :: getdouble
( FILE * fl ,
  char const * 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 const * 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 const * 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 const * 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 const * 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 const * cmd )
{
  if ( strcmp ( tmpch , cmd ) == 0 )
    return true ;
  else return false ;
}



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




// コマンドを比較
bool
readdata :: cmpcommand
( FILE * fl ,
  char const * cmd ,
  char const * 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 回避のため
}
