string
EnvironmentBase::DescribeValue( const Param& inParam, size_t inIdx1, size_t inIdx2 )
{
  ostringstream oss;
  oss << "Parameter \""
      << inParam.Section() << "->" << inParam.Name()
      << "\": Value";

  if( string( inParam.Type() ).find( "matrix" ) != string::npos )
    oss << " at index (" << inIdx1 + 1 << ", " << inIdx2 + 1 << ")";
  else if( string( inParam.Type() ).find( "list" ) != string::npos )
    oss << " at index " << inIdx1 + 1;

  return oss.str();
}
bool
EnvironmentBase::IsAutoConfigParam( const Param& p )
{
  enum { autoType = 0, autoTag, autoKind, count };
  static const char* s[][count] =
  {
    { "blob", 0 },
    { "auto", "AutoConfig", 0 },
    { "(enumeration)", 0 },
  };
  struct
  {
    bool Is( int type, const char* str )
    { 
      const char** p = s[type];
      while( *p )
        if( !::stricmp( *p++, str ) )
          return true;
      return false;
    }
    bool Contains( int type, const char* str )
    { 
      while( *str )
        if( Is( type, str++ ) )
          return true;
      return false;
    }
  } strings;

  bool result = strings.Is( autoType, p.Type().c_str() );
  if( p.NumValues() == 1 )
    result = result || strings.Is( autoTag, p.Value().c_str() );
  if( p.NumValues() > 0 && !::atoi( p.Value().c_str() ) )
    result = result || strings.Contains( autoKind, p.Comment().c_str() )
                       && strings.Contains( autoTag, p.Comment().c_str() );
  return result;
}
void
_TParamDef::param_add_all( ParamList* inList, const char* inSectionPrefix, long inDefaultDimension )
{
  string  sectionPrefix( inSectionPrefix ),
          externalPrefix( "ext_" ),
          runtimeSuffix( RUNTIME_SUFFIX ),
          runtimeElement( RUNTIME_ELEMENT );
  for( list<_TParamDef*>::const_iterator i = _TParamDef::params().begin();
        i != params().end(); ++i )
  {
    Param p( ( *i )->definitionLine() );
    string section = p.Section();
    if( section.find( externalPrefix ) != 0 )
    {
      if( section != sectionPrefix )
      {
         section = sectionPrefix + "_" + section;
         p.SetSection( section );
      }
      string name = p.Name();
      size_t suffixPos = name.find( runtimeSuffix );
      if( suffixPos != name.npos )
      {
        p.SetType( "matrix" );
        string value = p.Value();
        size_t pos = value.find( runtimeSuffix );
        p.SetDimensions( inDefaultDimension + 1, 1 );
        for( int i = p.NumRows() - 1; i >= 0; --i )
        {
          // Replace RUNTIME_SUFFIX in the comment and use it as a row label.
          ostringstream os;
          os << i;
          string comment = p.Comment();
          size_t comment_pos = comment.find( runtimeSuffix );
          if( comment_pos != comment.npos )
            comment.replace( comment_pos, runtimeSuffix.length(), os.str() );
          p.RowLabels()[ i ] = comment;
          // Replace RUNTIME_SUFFIX in the parameter values.
          if( pos == value.npos )
            p.Value( i, 0 ) = value;
          else
          {
            string newValue = value;
            newValue.replace( pos, runtimeSuffix.length(), os.str() );
            p.Value( i, 0 ) = newValue;
          }
        }
        p.ColumnLabels()[ 0 ] = "";

        ostringstream oss;
        oss << p;
        string line = oss.str();
        // Replace RUNTIME_SUFFIX in the parameter name.
        pos = line.find( runtimeSuffix );
        if( pos != line.npos )
          line.replace( pos, runtimeSuffix.length(), "" );
        // Replace RUNTIME_SUFFIX in the comment.
        pos = line.rfind( runtimeSuffix );
        if( pos != line.npos )
          line.replace( pos, runtimeSuffix.length(), "N" );
        name.replace( suffixPos, runtimeSuffix.length(), "" );
        if( !inList->Exists( name ) )
          inList->Add( line );
      }
      else
      { // The parameter might be a special instance for a certain suffix.
        // This will only work for true suffices, i.e. at the end of the name.
        size_t pos = name.find_last_not_of( "0123456789" );
        Param* param = NULL;
        if( pos != name.length() - 1 )
        {
          string paramName = name.substr( 0, pos + 1 );
          if( inList->Exists( paramName ) )
            param = &( *inList )[ paramName ];
        }
        if( param != NULL && string( "matrix" ) == param->Type() )
        {
          long suffix = ::atoi( name.substr( pos ).c_str() );
          param->Value( suffix, 0 ) = p.Value();
          param->RowLabels()[ suffix ] = p.Comment();
        }
        else if( !PARAM_EXISTS( inList, p.Name() ) )
        {
          ostringstream oss;
          oss << p;
          string line = oss.str();
          // Runtime elements are not supported, the user must supply a value.
          size_t rtPos;
          while( ( rtPos = line.find( runtimeElement ) ) != line.npos )
            line.replace( rtPos, runtimeElement.length(), "N/A" );
          inList->Add( line );
        }
      }
    }
  }
}