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

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <iomanip>

#include "kidenrt.hh"
#include "diapatrn.hh"
#include "rtss_iconv.hh"

//#define DEBUG


using std :: cerr ;
using std :: endl ;
using std :: ostringstream ;
using std :: fixed ;
using std :: setprecision ;



// feeder.dat を読むファイル
void
feeder :: rf_ffile
()
{
  if ( f_xml )
  {
    if ( ! s_xml )
    {
      cerr << "Error: XML-ised F File is incompatible with non-XML S file"
           << endl ;
      exit ( 1 ) ;
    }

    // -----
    // Loading file.
    // ファイルロード。
    // -----
    string f_file_full_path = "" ;
    if ( is_backslash )
    {
      f_file_full_path += f_drive_str ;
    }
    f_file_full_path += f_dir_str ;
    if ( is_backslash )
    {
      f_file_full_path += "\\" ;
    }
    else
    {
      f_file_full_path += "/" ;
    }
    f_file_full_path += f_file_str ;
    TiXmlDocument f_doc ( f_file_full_path ) ;
    bool loadOkay = f_doc . LoadFile () ;
    if ( ! loadOkay )
    {
      cerr << "Failed to load file \"" << f_file_full_path << "\"." << endl ;
      exit ( 1 ) ;
    }

    // -----
    // The file must have one "root" element of tag <rtss_f_file>.
    // If multiple <rtss_f_file> tags exist, only the first one is read.
    // このXMLファイルには <rtss_f_file> というタグがなければならない。
    // <rtss_f_file> タグが複数あれば最初のだけを読む。
    // -----
    const TiXmlNode * f_doc_ch = f_doc . FirstChild () ;
    while ( f_doc_ch && f_doc_ch -> Type () != TiXmlNode :: TINYXML_ELEMENT )
    {
      f_doc_ch = f_doc_ch -> NextSibling () ;
    }
    if ( ! f_doc_ch
         || f_doc_ch -> Type () != TiXmlNode :: TINYXML_ELEMENT
         || string ( f_doc_ch -> Value () ) != "rtss_f_file" )
    {
      cerr << "Failed to find element \"rtss_f_file\"" << endl
           << " in file \"" << f_file_full_path << "\"." << endl ;
      exit ( 1 ) ;
    }

    // -----
    // Getting child element(s) of tag <rtss_f_file>.
    // Tags must appear in this order:-
    //  <f_options>: One appearance, cannot be omitted.
    //  <feedlines>: One appearances, cannot be omitted.
    //  <connections>: One appearance, cannot be omitted.
    // <rtss_f_file> の子を取得. 以下の順で現れる必要がある。
    //  <f_options>: 1カ所必須。
    //  <feedlines>: 1カ所必須。
    //  <connections>: 1カ所必須。
    // -----
    bool has_options_tag = false ;
    bool has_feedlines_tag = false ;
    bool has_connections_tag = false ;
    for ( const TiXmlNode * f_doc_cc = f_doc_ch -> FirstChild () ;
          f_doc_cc ; f_doc_cc = f_doc_cc -> NextSibling () )
    {
      // -----
      // Ignore non-Element node.
      // エレメント以外は無視。
      // -----
      if ( f_doc_cc -> Type () != TiXmlNode :: TINYXML_ELEMENT )
        continue ;

      // -----
      // Check tag name.
      // タグ名チェック。
      // -----
      string sdcc_val = string ( f_doc_cc -> Value () ) ;
      if ( sdcc_val == "f_options" )
      {
        // -----
        // Processing <f_options> tag.
        // <f_options> タグを処理.
        // -----
        if ( has_options_tag )
        {
          cerr << "Error: \"" << sdcc_val
               << "\" tag not allowed multiple times." << endl ;
          exit ( 1 ) ;
        }
        rf_fxml_options ( f_doc_cc ) ;
        has_options_tag = true ;
      }
      else if ( sdcc_val == "feedlines" )
      {
        // -----
        // Processing <feedlines> tag.
        // <feedlines> タグを処理.
        // -----
        if ( has_feedlines_tag )
        {
          cerr << "Error: \"" << sdcc_val
               << "\" tag not allowed multiple times." << endl ;
          exit ( 1 ) ;
        }
        if ( ! has_options_tag )
        {
          cerr << "Error: \"" << sdcc_val
               << "\" tag not allowed before <f_options> tag." << endl ;
          exit ( 1 ) ;
        }
        rf_fxml_feedlines ( f_doc_cc ) ;
        has_feedlines_tag = true ;
      }
      else if ( sdcc_val == "connections" )
      {
        // -----
        // Processing <connections> tag.
        // <connections> タグを処理.
        // -----
        if ( has_connections_tag )
        {
          cerr << "Error: \"" << sdcc_val
               << "\" tag not allowed multiple times." << endl ;
          exit ( 1 ) ;
        }
        if ( ! has_options_tag )
        {
          cerr << "Error: \"" << sdcc_val
               << "\" tag not allowed before <f_options> tag." << endl ;
          exit ( 1 ) ;
        }
        if ( ! has_feedlines_tag )
        {
          cerr << "Error: \"" << sdcc_val
               << "\" tag not allowed before <feedlines> tag." << endl ;
          exit ( 1 ) ;
        }
        rf_fxml_connections ( f_doc_cc ) ;
        has_connections_tag = true ;
      }
      else
      {
        cerr << "Error: \"" << sdcc_val << "\" tag not allowed." << endl ;
        exit ( 1 ) ;
      }
    }
    if ( ! has_options_tag )
    {
      cerr << "Error: <f_options> tag missing in XML F file." << endl ;
      exit ( 1 ) ;
    }
    if ( ! has_feedlines_tag )
    {
      cerr << "Error: <feedlines> tag missing in XML F file." << endl ;
      exit ( 1 ) ;
    }
    if ( ! has_connections_tag )
    {
      cerr << "Error: <connections> tag missing in XML F file." << endl ;
      exit ( 1 ) ;
    }
  }
  else
  {
    FILE * feeddat = fopen ( f_file , "r" ) ;
    if ( ! feeddat ) err_access ( f_file ) ;
    int sia ;
    double sda ;
    ostringstream o_ff ;
    while ( 1 )
    {
      getcommand ( feeddat , f_file ) ;
      if ( cmpcommand ( "feeders" ) )
      {
        // while 文を抜ける
        break ;
      }
      else if ( cmpcommand ( "nominal_voltage" ) )
      {
        getdouble ( feeddat , f_file , nominal_volt ) ;
        o_ff . clear () ;
        o_ff . str ( "" ) ;
        o_ff << "nominal voltage = " << fixed << setprecision ( 1 )
             << nominal_volt << " " ;
        l_ofs << o_ff . str () << endl ;
      }
      else if ( cmpcommand ( "options" ) )
      {
        getcommand ( feeddat , f_file ) ;
        if ( cmpcommand ( "ccalresult" ) )
        {
          if ( g_sw_ccalresult )
          {
            g_sw_ccalresult = false ;
            l_ofs << "OK, toggled g_sw_ccalresult to false" << endl ;
          }
          else
          {
            g_sw_ccalresult = true ;
            l_ofs << "OK, toggled g_sw_ccalresult to true" << endl ;
          }
        }
        else if ( cmpcommand( "ssdirection" ) )
        {
          if ( g_sw_ss_direction )
          {
            g_sw_ss_direction = false ;
            l_ofs << "OK, toggled g_sw_ss_direction to false" << endl ;
          }
          else
          {
            g_sw_ss_direction = true ;
            l_ofs << "OK, toggled g_sw_ss_direction to true" << endl ;
          }
        }
        else if ( cmpcommand ( "kilowatt_subout" ) )
        {
          if ( g_sw_kilowatt_subout )
          {
            g_sw_kilowatt_subout = false ;
            l_ofs << "OK, toggled g_sw_kilowatt_subout to false" << endl ;
          }
          else
          {
            g_sw_kilowatt_subout = true ;
            l_ofs << "OK, toggled g_sw_kilowatt_subout to true" << endl ;
          }
        }
        else if ( cmpcommand ( "per_car_out" ) )
        {
          if ( g_sw_per_car_out )
          {
            g_sw_per_car_out = false ;
            l_ofs << "OK, toggled g_sw_per_car_out to false" << endl ;
          }
          else
          {
            g_sw_per_car_out = true ;
            l_ofs << "OK, toggled g_sw_per_car_out to true" << endl ;
          }
        }
        else if ( cmpcommand ( "nosetviold" ) )
        {
          if ( g_sw_nosetviold )
          {
            g_sw_nosetviold = false ;
            l_ofs << "OK, toggled g_sw_nosetviold to false" << endl ;
          }
          else
          {
            g_sw_nosetviold = true ;
            l_ofs << "OK, toggled g_sw_nosetviold to true" << endl ;
          }
        }
        else if ( cmpcommand ( "csv_has_noshibo" ) )
        {
          if ( g_sw_csv_has_noshibo )
          {
            g_sw_csv_has_noshibo = false ;
            l_ofs << "OK, toggled g_sw_csv_has_noshibo to false" << endl ;
          }
          else
          {
            g_sw_csv_has_noshibo = true ;
            l_ofs << "OK, toggled g_sw_csv_has_noshibo to true" << endl ;
          }
        }
        else if ( cmpcommand ( "csv_has_rnotch_for_capper" ) )
        {
          if ( g_sw_csv_has_rnotch_for_capper )
          {
            g_sw_csv_has_rnotch_for_capper = false ;
            l_ofs << "OK, toggled g_sw_csv_has_rnotch_for_capper to false"
                  << endl ;
          }
          else
          {
            g_sw_csv_has_rnotch_for_capper = true ;
            l_ofs << "OK, toggled g_sw_csv_has_rnotch_for_capper to true"
                  << endl ;
          }
        }
        else if ( cmpcommand ( "csv_without_quotation" ) )
        {
          if ( g_sw_csv_without_quotation )
          {
            g_sw_csv_without_quotation = false ;
            l_ofs << "OK, toggled g_sw_csv_without_quotation to false"
                  << endl ;
          }
          else
          {
            g_sw_csv_without_quotation = true ;
            l_ofs << "OK, toggled g_sw_csv_without_quotation to true"
                  << endl ;
          }
        }
        else err_eof ( f_file ) ;
      }
      else err_eof ( f_file ) ;
    }
    getint ( feeddat , f_file , feeders ) ;
    l_ofs << "feeder setvar = " <<  feeders << " " ;

    // dp_command の読み込み
    getcommand ( feeddat , f_file ) ;

    // 初期化 : -Wall warning 回避のため
    dp_command dpcmx = No_comm ;
    if ( cmpcommand ( "Delay_yes" ) )
      dpcmx = Delay_yes ;
    else if ( cmpcommand ( "Buffer_yes" ) )
      dpcmx = Buffer_yes ;
    else if ( ! ( cmpcommand ( "No_comm" ) ) )
      err_eof ( f_file ) ;
    l_ofs << tmpch << endl ;

    // dp_command のセット
    for ( vector < diapattern * > :: iterator ii = vec_dpt . begin () ;
          ii != vec_dpt . end () ; ++ ii )
    {
      ( * ii ) -> setdc ( dpcmx ) ;
    }

    // feedline 配列の確保
    for ( int i = 0 ; i < feeders ; ++ i )
    {
      feedline * x = new feedline ;
      if ( ! x )
      {
        cerr << "Error: memory allocation fault" << endl ;
        exit ( 37 ) ;
      }
      vec_fln . push_back ( x ) ;

      // *** feedline object に饋電線番号を伝達
      getFLN ( i ) . setnfline ( i ) ;
      getFLN ( i ) . renewssc ( nss + ncar ) ;
    }
    getcommand ( feeddat , f_file ) ;
    cmpcommand ( "freeruns" , f_file ) ;
    getint ( feeddat , f_file , nfree ) ;
    l_ofs << "free running cycle(s) = " << nfree << endl ;
    getcommand ( feeddat , f_file ) ;
    cmpcommand ( "simulatings" , f_file ) ;
    getint ( feeddat , f_file , nsim ) ;
    l_ofs << "simulating cycle(s) = " << nsim << endl ;

    // 饋電線の形状、饋電定数、長さ
    double sdb ;

    // 初期化: -Wall warning 回避のため
    feeder_shape fsp = Long ;

    for ( int i = 0 ; i < feeders ; ++ i )
    {
      getcommand ( feeddat , f_file ) ;
      if ( strcmp ( tmpch , "setfeedline" ) != 0 )
        err_eof ( f_file ) ;
      if ( gettwodbls ( feeddat , sda , sdb ) == EOF )
        err_eof ( f_file ) ;
      getcommand ( feeddat , f_file ) ;
      static char tcx [ TMPCHSIZ ] ;
      strcpy ( tcx , tmpch ) ;
      if ( strcmp ( tmpch , "Long" ) == 0 )
        fsp = Long ;
      else if ( strcmp ( tmpch , "0" ) == 0 )
      {
        fsp = Long ;
        strcpy ( tcx , "Long" ) ;
      }
      else if ( strcmp ( tmpch , "Circle" ) == 0 )
        fsp = Circle ;
      else if ( strcmp ( tmpch , "1" ) == 0 )
      {
        fsp = Circle ;
        strcpy ( tcx , "Circle" ) ;
      }
      else
        err_eof ( f_file ) ;
      o_ff . clear () ;
      o_ff . str ( "" ) ;
      o_ff << "feedline ( " << i << " ) set variables: " << fixed
           << setprecision ( 3 ) << sda << " " << setprecision ( 5 ) << sdb
           << " " << tcx ;
      l_ofs << o_ff . str () << endl ;
      getFLN ( i ) . setvar ( sda , sdb , fsp ) ;
    }

    // 変電所接続点データ→ feedline, elecchar (sub)
    getcommand ( feeddat , f_file ) ;
    if ( strcmp ( tmpch , "ssfeederconnections" ) != 0 ) err_eof ( f_file ) ;
    if ( getint ( feeddat , sia ) == EOF ) err_eof ( f_file ) ;
    l_ofs << "number of substation/feeder connection data = " << sia << endl ;
    feedpos fp ;
    ssfeedconnect sfcn ;
    for ( int i = 0 ; i < sia ; ++ i )
    {
      gettwoints ( feeddat , f_file , fp . nfline , fp . csno ) ;
      getthreedbls ( feeddat , f_file , fp . pos , fp . sttimp , fp . endimp ) ;
      if ( fp . nfline < 0 || fp . nfline >= feeders
           || fp . csno < 0 || fp . csno >= nss )
        err_eof ( f_file ) ;
      o_ff . clear () ;
      o_ff . str ( "" ) ;
      o_ff << "feedline( " << fp . nfline << " ) *= " << fp . csno << " "
           << fixed << setprecision ( 4 ) << fp . pos << " "
           << setprecision ( 5 ) << fp . sttimp << " " << fp . endimp ;
      l_ofs << o_ff . str () << endl ;
      getFLN ( fp . nfline ) *= fp ;
      sfcn = fp ;

      // Error not found. Add the connection data into substation.
      // エラー見つからず。直接たたき込む
      getSUB ( fp . csno ) . feedcon () += sfcn ;
    }
    fclose ( feeddat ) ;
  }

  // 行列の大きさ初期化
  ymtx . renewmn ( ncss , ncss ) ;
  gff_xx . renewmn ( ncss , ncss ) ;
  gamma . renewmn ( ncss ) ;
  fvec . renewmn ( ncss ) ;

  // 簡単なデータチェック
  bool patc = false ;
  for ( int i = 1 ; i < ndp ; ++ i )
  {
    if ( getDPT ( i ) . ptntime () != getDPT ( i - 1 ) . ptntime () )
      patc = true ;
  }
  if ( patc )
  {
    cerr << "Error: Cycle times must be uniform across all diagram patterns."
         << endl << " Check the N-file." << endl ;
    exit ( 1 ) ;
  }
  t_cyc = getDPT ( 0 ) . ptntime () ;
}



bool
processBooleanAttribute
( TiXmlAttribute const * _ax ,
  string _err_msg )
{
  string _s_ax = _ax -> ValueStr () ;
  if ( _s_ax  == "true" || _s_ax == "True" || _s_ax == "t" || _s_ax == "T"
       || _s_ax == "TRUE" || _s_ax == "Y" || _s_ax == "yes"
       || _s_ax == "y" || _s_ax == "YES" )
  {
    return true ;
  }
  else if ( _s_ax  == "false" || _s_ax == "False" || _s_ax == "f"
            || _s_ax == "F" || _s_ax == "FALSE" || _s_ax == "N"
            || _s_ax == "no" || _s_ax == "n" || _s_ax == "NO" )
  {
    return false ;
  }
  else
  {
    cerr << "Error: " << _err_msg << endl ;
    exit ( 1 ) ;
  }
}



// ----
// Processing <f_options> tag.
// <f_options> タグの処理。
// ----
void
feeder :: rf_fxml_options
( TiXmlNode const * _nx )
{
  // -----
  // All options are to be specified by the attribute of this tag. Any
  // elements within this tag will be ignored.
  // すべてのオプションはこのタグの属性によって指定される。このタグが持つ
  // 要素は無視される。
  // -----
  ostringstream o_ff ;
  dp_command dpcmx = No_comm ;
  bool sw_freeruns_not_set = true ;
  bool sw_simulatings_not_set = true ;
  for ( TiXmlAttribute const *
          _ax = _nx -> ToElement () -> FirstAttribute () ; _ax ;
        _ax = _ax -> Next () )
  {
    if ( string ( _ax -> Name () ) == "freeruns" )
    {
      // attribute "freeruns"
      sscanf ( _ax -> Value () , "%d" , & nfree ) ;
      l_ofs << "F option: free running cycle(s) = " << nfree << endl ;
      sw_freeruns_not_set = false ;
    }
    else if ( string ( _ax -> Name () ) == "simulatings" )
    {
      // attribute "simulatings"
      sscanf ( _ax -> Value () , "%d" , & nsim ) ;
      l_ofs << "F option: simulating cycle(s) = " << nsim << endl ;
      sw_simulatings_not_set = false ;
    }
    else if ( string ( _ax -> Name () ) == "nominal_voltage" )
    {
      // attribute "nominal_voltage"
      sscanf ( _ax -> Value () , "%lf" , & nominal_volt ) ;
      o_ff . clear () ;
      o_ff . str ( "" ) ;
      o_ff << "F option: nominal voltage = " << fixed << setprecision ( 1 )
           << nominal_volt << " " ;
      l_ofs << o_ff . str () << endl ;
    }
    else if ( string ( _ax -> Name () ) == "ccalresult" )
    {
      string _err_cc ( "option ccalresult incorrect" ) ;
      g_sw_ccalresult = processBooleanAttribute ( _ax , _err_cc ) ;
      if ( g_sw_ccalresult )
      {
        l_ofs << "F Option: ccalresult = true" << endl ;
      }
      else
      {
        l_ofs << "F Option: ccalresult = false" << endl ;
      }
    }
    else if ( string ( _ax -> Name () ) == "ssdirection" )
    {
      string _err_ssd ( "option ssdirection incorrect" ) ;
      g_sw_ss_direction = processBooleanAttribute ( _ax , _err_ssd ) ;
      if ( g_sw_ss_direction )
      {
        l_ofs << "F Option: ssdirection = true" << endl ;
      }
      else
      {
        l_ofs << "F Option: ssdirection = false" << endl ;
      }
    }
    else if ( string ( _ax -> Name () ) == "kilowatt_subout" )
    {
      string _err_kwo ( "option kilowatt_subout incorrect" ) ;
      g_sw_kilowatt_subout = processBooleanAttribute ( _ax , _err_kwo ) ;
      if ( g_sw_kilowatt_subout )
      {
        l_ofs << "F Option: kilowatt_subout = true" << endl ;
      }
      else
      {
        l_ofs << "F Option: kilowatt_subout = false" << endl ;
      }
    }
    else if ( string ( _ax -> Name () ) == "per_car_out" )
    {
      string _err_pco ( "option per_car_out incorrect" ) ;
      g_sw_per_car_out = processBooleanAttribute ( _ax , _err_pco ) ;
      if ( g_sw_per_car_out )
      {
        l_ofs << "F Option: per_car_out = true" << endl ;
      }
      else
      {
        l_ofs << "F Option: per_car_out = false" << endl ;
      }
    }
    else if ( string ( _ax -> Name () ) == "nosetviold" )
    {
      string _err_nso ( "option nosetviold incorrect" ) ;
      g_sw_nosetviold = processBooleanAttribute ( _ax , _err_nso ) ;
      if ( g_sw_nosetviold )
      {
        l_ofs << "F Option: nosetviold = true" << endl ;
      }
      else
      {
        l_ofs << "F Option: nosetviold = false" << endl ;
      }
    }
    else if ( string ( _ax -> Name () ) == "csv_has_noshibo" )
    {
      string _err_chn ( "option csv_has_noshibo incorrect" ) ;
      g_sw_csv_has_noshibo = processBooleanAttribute ( _ax , _err_chn ) ;
      if ( g_sw_csv_has_noshibo )
      {
        l_ofs << "F Option: csv_has_noshibo = true" << endl ;
      }
      else
      {
        l_ofs << "F Option: csv_has_noshibo = false" << endl ;
      }
    }
    else if ( string ( _ax -> Name () ) == "csv_has_rnotch_for_capper" )
    {
      string _err_chr ( "option csv_has_rnotch_for_capper incorrect" ) ;
      g_sw_csv_has_rnotch_for_capper
        = processBooleanAttribute ( _ax , _err_chr ) ;
      if ( g_sw_csv_has_rnotch_for_capper )
      {
        l_ofs << "F Option: csv_has_rnotch_for_capper = true" << endl ;
      }
      else
      {
        l_ofs << "F Option: csv_has_rnotch_for_capper = false" << endl ;
      }
    }
    else if ( string ( _ax -> Name () ) == "csv_without_quotation" )
    {
      string _err_woq ( "option csv_without_quotation incorrect" ) ;
      g_sw_csv_without_quotation = processBooleanAttribute ( _ax , _err_woq ) ;
      if ( g_sw_csv_without_quotation )
      {
        l_ofs << "F Option: csv_without_quotation = true" << endl ;
      }
      else
      {
        l_ofs << "F Option: csv_without_quotation = false" << endl ;
      }
    }
    else if ( string ( _ax -> Name () ) == "dp_command" )
    {
      string _dpc_v = _ax -> ValueStr () ;
      if ( _dpc_v == "No_comm" )
      {
        dpcmx = No_comm ;
      }
      else if ( _dpc_v == "Delay_yes" )
      {
        dpcmx = Delay_yes ;
      }
      else if ( _dpc_v == "Buffer_yes" )
      {
        dpcmx = Buffer_yes ;
      }
      else
      {
        cerr << "Error: dp_command attribute with incorrect value \""
             << _dpc_v << "\" in the setting of F options" << endl ;
        exit ( 1 ) ;
      }
      l_ofs << "F Option: dp_command = " << _dpc_v << endl ;
    }
    else
    {
      cerr << "ERROR: tag <f_options> with incorrect attribute "
           << _ax -> Name () << endl ;
      exit ( 1 ) ;
    }
  }

  if ( sw_freeruns_not_set )
  {
    cerr << "ERROR: tag <f_options> without attribute freeruns" << endl ;
    exit ( 1 ) ;
  }
  if ( sw_simulatings_not_set )
  {
    cerr << "ERROR: tag <f_options> without attribute simulatings" << endl ;
    exit ( 1 ) ;
  }

  // ----
  // Setting dp_command
  // ----
  for ( vector < diapattern * > :: iterator ii = vec_dpt . begin () ;
        ii != vec_dpt . end () ; ++ ii )
  {
    ( * ii ) -> setdc ( dpcmx ) ;
  }
}



// ----
// Processing <feedlines> tag.
// <feedlines> タグの処理。
// ----
void
feeder :: rf_fxml_feedlines
( TiXmlNode const * _nx )
{
  ostringstream o_ff ;

  // -----
  // The given TiXmlNode is of tag <feedlines>, which contains one or more
  // <setfeedline> tags.
  // 引数として与えられた TiXmlNode は <feedlines> タグのもの。このタグは
  // 1つまたはそれ以上の <setfeedline> タグを子タグとして持つ。
  // -----
  vector < feedline * > :: size_type _nfln = 0 ;
  for ( TiXmlNode const * _xc = _nx -> FirstChild () ; _xc ;
        _xc = _xc -> NextSibling () )
  {
    // -----
    // Ignore non-Element node.
    // エレメント以外は無視。
    // -----
    if ( _xc -> Type () != TiXmlNode :: TINYXML_ELEMENT )
      continue ;

    // -----
    // Check tag name.
    // タグ名チェック。
    // -----
    string _xc_val = string ( _xc -> Value () ) ;
    if ( _xc_val != "setfeedline" )
    {
      cerr << "ERROR: tag <feedlines> with incorrect child tag <"
           << _xc_val << ">" << endl ;
      exit ( 1 ) ;
    }

    // -----
    // Scan and process attributes of <setfeedline>. There must be:
    //  name: the name of the feedline (string)
    //  length: the length of this feedline object in [km]
    //  resistance: per-km resistance in [ohm/km]
    //  shape: either "Long" or "Circle"
    // -----
    bool sw_name_not_found = true ;
    string _name_of_the_fln ;
    string _name_sjis_of_the_fln ;
    bool sw_length_not_found = true ;
    double _length = 0 ;
    bool sw_resistance_not_found = true ;
    double _resistance = 0 ;
    bool sw_shape_not_found = true ;
    feeder_shape _fsp = Long ;
    string _fsps ;
    for ( TiXmlAttribute const *
            _ax = _xc -> ToElement () -> FirstAttribute () ; _ax ;
          _ax = _ax -> Next () )
    {
      if ( string ( _ax -> Name () ) == "name" )
      {
        // attribute "name"
        _name_of_the_fln = _ax -> ValueStr () ;
#ifdef SJIS_ICONV
        // Enable this on Japanese Windows environment only
        iconv_t ixx = iconv_open ( "SHIFT_JIS" , "UTF-8" ) ;
        if ( ixx == ( iconv_t ) ( - 1 ) )
        {
          cerr << "ERROR: ICONV initialisation failed (feedline)" << endl ;
          exit ( 1 ) ;
        }
        string :: size_type len = _name_of_the_fln . length () ;
        char * buf_out = new char [ len + 1 ] ;
        convertFromUTF8ToSJIS ( _name_of_the_fln . c_str () , buf_out , len ) ;
        _name_sjis_of_the_fln = string ( buf_out ) ;
        delete [] buf_out ;
#else
        _name_sjis_of_the_fln = _name_of_the_fln ;
#endif
        sw_name_not_found = false ;
      }
      else if ( string ( _ax -> Name () ) == "length" )
      {
        // attribute "length"
        sscanf ( _ax -> Value () , "%lf" , & _length ) ;
        sw_length_not_found = false ;
      }
      else if ( string ( _ax -> Name () ) == "resistance" )
      {
        // attribute "resistance"
        sscanf ( _ax -> Value () , "%lf" , & _resistance ) ;
        sw_resistance_not_found = false ;
      }
      else if ( string ( _ax -> Name () ) == "shape" )
      {
        // attribute "shape"
        _fsps = _ax -> ValueStr () ;
        if ( _fsps == "Long" )
        {
          _fsp = Long ;
        }
        else if ( _fsps == "Circle" )
        {
          _fsp = Circle ;
        }
        else
        {
          cerr << "Error: tag <setfeedline> has shape attribute "
               << "with wrong value \"" << _fsps << "\"" << endl ;
          exit ( 1 ) ;
        }
        sw_shape_not_found = false ;
      }
      else
      {
        cerr << "Error: tag <setfeedline> with incorrect attribute \""
             << _ax -> Name () << "\"" << endl ;
        exit ( 1 ) ;
      }
    }
    if ( sw_name_not_found )
    {
      cerr << "Error: attribute \"name\" not found in tag <setfeedline>"
           << endl ;
      exit ( 1 ) ;
    }
    if ( sw_length_not_found )
    {
      cerr << "Error: attribute \"length\" not found in tag <setfeedline>"
           << endl ;
      exit ( 1 ) ;
    }
    if ( sw_resistance_not_found )
    {
      cerr << "Error: attribute \"resistance\" not found in tag <setfeedline>"
           << endl ;
      exit ( 1 ) ;
    }
    if ( sw_shape_not_found )
    {
      cerr << "Error: attribute \"shape\" not found in tag <setfeedline>"
           << endl ;
      exit ( 1 ) ;
    }

    feedline * x = new feedline ;
    if ( ! x )
    {
      cerr << "Error: memory allocation fault when creating a feedline object"
           << endl ;
      exit ( 1 ) ;
    }
    x -> setnfline ( _nfln ) ;
    x -> renewssc ( nss + ncar ) ;
    o_ff . clear () ;
    o_ff . str ( "" ) ;
    o_ff << "feedline ( " << _nfln << " ) set variables: " << fixed
         << setprecision ( 3 ) << _length << " " << setprecision ( 5 )
         << _resistance << " " << _fsps ;
    l_ofs << o_ff . str () << endl ;
    x -> setvar ( _length , _resistance , _fsp ) ;
    x -> setName ( _name_of_the_fln ) ;
    x -> setNameSjis ( _name_sjis_of_the_fln ) ;
    vec_fln . push_back ( x ) ;

    // -----
    // Save the pointer in map _fln. The name (key for the map) can be
    // extracted from the object itself.
    // ポインタを，_fln マップに格納。マップのキーとして利用する名前は
    // オブジェクトそのものから取り出すことができる。
    // -----
    if ( _fln . find ( x -> getName () ) != _fln . end () )
    {
      cerr << "Error: duplicate name found in XML F file." << endl ;
      exit ( 1 ) ;
    }
    _fln [ x -> getName () ] = _nfln ;
    ++ _nfln ;
  }
  feeders = _nfln ;

  // ----
  // Setting nfline in nextsta objects.
  // ----
  for ( vector < diapattern * > :: iterator ii = vec_dpt . begin () ;
        ii != vec_dpt . end () ; ++ ii )
  {
    for ( diapattern :: np_iterator jj = ( * ii ) -> np_begin () ;
          jj != ( * ii ) -> np_end () ; ++ jj )
    {
      ( * jj ) -> setFeedlineNumber ( _fln ) ;
    }
  }
}




// ----
// Processing <connections> tag.
// <connections> タグの処理。
// ----
void
feeder :: rf_fxml_connections
( TiXmlNode const * _nx )
{
  ostringstream o_ff ;

  // -----
  // The given TiXmlNode is of tag <connections>, which contains one or more
  // <connection> tags.
  // 引数として与えられた TiXmlNode は <connections> タグのもの。このタグは
  // 1つまたはそれ以上の <connection> タグを子タグとして持つ。
  // -----
  for ( TiXmlNode const * _xc = _nx -> FirstChild () ; _xc ;
        _xc = _xc -> NextSibling () )
  {
    // -----
    // Ignore non-Element node.
    // エレメント以外は無視。
    // -----
    if ( _xc -> Type () != TiXmlNode :: TINYXML_ELEMENT )
      continue ;

    // -----
    // Check tag name.
    // タグ名チェック。
    // -----
    string _xc_val = string ( _xc -> Value () ) ;
    if ( _xc_val != "connection" )
    {
      cerr << "ERROR: tag <connections> with incorrect child tag <"
           << _xc_val << ">" << endl ;
      exit ( 1 ) ;
    }

    // -----
    // Scan and process attributes of <connection>. There must be:
    //  substation: name of the substation.
    //  feedline: name of the feedline.
    //  position: connecting position in [km].
    //  impedance_begin: impedance of the feeder between substation and
    //     track, beginning_of_line side
    //  impedance_end: impedance of the feeder between substation and
    //     track, end_of_line side
    // -----
    bool sw_substation_not_found = true ;
    string _name_of_the_substation ;
    bool sw_feedline_not_found = true ;
    string _name_of_the_feedline ;
    bool sw_position_not_found = true ;
    double _position = 0 ;
    bool sw_impedance_begin_not_found = true ;
    double _impedance_begin = 0 ;
    bool sw_impedance_end_not_found = true ;
    double _impedance_end = 0 ;
    for ( TiXmlAttribute const *
            _ax = _xc -> ToElement () -> FirstAttribute () ; _ax ;
          _ax = _ax -> Next () )
    {
      if ( string ( _ax -> Name () ) == "position" )
      {
        // attribute "position"
        sscanf ( _ax -> Value () , "%lf" , & _position ) ;
        sw_position_not_found = false ;
      }
      else if ( string ( _ax -> Name () ) == "impedance_begin" )
      {
        // attribute "impedance_begin"
        sscanf ( _ax -> Value () , "%lf" , & _impedance_begin ) ;
        sw_impedance_begin_not_found = false ;
      }
      else if ( string ( _ax -> Name () ) == "impedance_end" )
      {
        // attribute "impedance_end"
        sscanf ( _ax -> Value () , "%lf" , & _impedance_end ) ;
        sw_impedance_end_not_found = false ;
      }
      else if ( string ( _ax -> Name () ) == "substation" )
      {
        // attribute "substation"
        _name_of_the_substation = _ax -> ValueStr () ;
        sw_substation_not_found = false ;
      }
      else if ( string ( _ax -> Name () ) == "feedline" )
      {
        // attribute "feedline"
        _name_of_the_feedline = _ax -> ValueStr () ;
        sw_feedline_not_found = false ;
      }
      else
      {
        cerr << "Error: tag <connection> with incorrect attribute \""
             << _ax -> Name () << "\"" << endl ;
        exit ( 1 ) ;
      }
    }
    if ( sw_substation_not_found )
    {
      cerr << "Error: attribute \"substation\" not found in tag <connection>"
           << endl ;
      exit ( 1 ) ;
    }
    if ( sw_feedline_not_found )
    {
      cerr << "Error: attribute \"feedline\" not found in tag <connection>"
           << endl ;
      exit ( 1 ) ;
    }
    if ( sw_position_not_found )
    {
      cerr << "Error: attribute \"position\" not found in tag <connection>"
           << endl ;
      exit ( 1 ) ;
    }
    if ( sw_impedance_begin_not_found )
    {
      cerr << "Error: attribute \"impedance_begin\" not found in tag "
           << "<connection>" << endl ;
      exit ( 1 ) ;
    }
    if ( sw_impedance_end_not_found )
    {
      cerr << "Error: attribute \"impedance_end\" not found in tag "
           << "<connection>" << endl ;
      exit ( 1 ) ;
    }

    map < string , vector < elecchar * > :: size_type > :: const_iterator
      i_substation = _sub . find ( _name_of_the_substation ) ;
    if ( i_substation == _sub . end () )
    {
      cerr << "Error: in tag <connection>, substation \""
           << _name_of_the_substation << "\" not found" << endl ;
      exit ( 1 ) ;
    }
    map < string , vector < feedline * > :: size_type > :: const_iterator
      i_feedline = _fln . find ( _name_of_the_feedline ) ;
    if ( i_feedline == _fln . end () )
    {
      cerr << "Error: in tag <connection>, feedline \""
           << _name_of_the_feedline << "\" not found" << endl ;
      exit ( 1 ) ;
    }
    
    feedpos _fp ;
    _fp . nfline = i_feedline -> second ;
    _fp . csno = i_substation -> second ;
    _fp . pos = _position ;
    _fp . sttimp = _impedance_begin ;
    _fp . endimp = _impedance_end ;
    o_ff . clear () ;
    o_ff . str ( "" ) ;
    o_ff << "feedline( " << _fp . nfline << " ) *= " << _fp . csno << " "
         << fixed << setprecision ( 4 ) << _fp . pos << " "
         << setprecision ( 5 ) << _fp . sttimp << " " << _fp . endimp ;
    l_ofs << o_ff . str () << endl ;
    getFLN ( _fp . nfline ) *= _fp ;
    ssfeedconnect _sfcn = _fp ;
    getSUB ( _fp . csno ) . feedcon () += _sfcn ;
  }
}
