void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
{
  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
  int numNonSwitchStrings = nonSwitchStrings.Size();
  if (numNonSwitchStrings < kMinNonSwitchWords)
    ThrowUserErrorException();

  if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
    ThrowUserErrorException();

  options.TechMode = parser[NKey::kTechMode].ThereIs;
  options.CalcCrc = parser[NKey::kCalcCrc].ThereIs;

  if (parser[NKey::kCaseSensitive].ThereIs)
    g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);

  NRecursedType::EEnum recursedType;
  if (parser[NKey::kRecursed].ThereIs)
    recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
  else
    recursedType = NRecursedType::kNonRecursed;

  g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1);
  UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8);

  bool thereAreSwitchIncludes = false;
  if (parser[NKey::kInclude].ThereIs)
  {
    thereAreSwitchIncludes = true;
    AddSwitchWildCardsToCensor(options.WildcardCensor,
        parser[NKey::kInclude].PostStrings, true, recursedType, codePage);
  }
  if (parser[NKey::kExclude].ThereIs)
    AddSwitchWildCardsToCensor(options.WildcardCensor,
        parser[NKey::kExclude].PostStrings, false, recursedType, codePage);
 
  int curCommandIndex = kCommandIndex + 1;
  bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&
      options.Command.CommandType != NCommandType::kBenchmark &&
      options.Command.CommandType != NCommandType::kInfo;

  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
  bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList;

  if (isExtractOrList && options.StdInMode)
    thereIsArchiveName = false;

  if (thereIsArchiveName)
  {
    if (curCommandIndex >= numNonSwitchStrings)
      ThrowUserErrorException();
    options.ArchiveName = nonSwitchStrings[curCommandIndex++];
  }

  AddToCensorFromNonSwitchesStrings(
      curCommandIndex, options.WildcardCensor,
      nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);

  options.YesToAll = parser[NKey::kYes].ThereIs;


  #ifndef _NO_CRYPTO
  options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
  if (options.PasswordEnabled)
    options.Password = parser[NKey::kPassword].PostStrings[0];
  #endif

  options.ShowDialog = parser[NKey::kShowDialog].ThereIs;

  if (parser[NKey::kArchiveType].ThereIs)
    options.ArcType = parser[NKey::kArchiveType].PostStrings[0];

  if (isExtractOrList)
  {
    if (!options.WildcardCensor.AllAreRelative())
      ThrowException("Cannot use absolute pathnames for this command");

    NWildcard::CCensor archiveWildcardCensor;

    if (parser[NKey::kArInclude].ThereIs)
      AddSwitchWildCardsToCensor(archiveWildcardCensor,
          parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);
    if (parser[NKey::kArExclude].ThereIs)
      AddSwitchWildCardsToCensor(archiveWildcardCensor,
          parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);

    if (thereIsArchiveName)
      AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);

    #ifdef _WIN32
    ConvertToLongNames(archiveWildcardCensor);
    #endif

    archiveWildcardCensor.ExtendExclude();

    if (options.StdInMode)
    {
      UString arcName = parser[NKey::kStdIn].PostStrings.Front();
      options.ArchivePathsSorted.Add(arcName);
      options.ArchivePathsFullSorted.Add(arcName);
    }
    else
    {
      EnumerateDirItemsAndSort(archiveWildcardCensor,
        options.ArchivePathsSorted,
        options.ArchivePathsFullSorted);
    }
    
    if (isExtractGroupCommand)
    {
      SetMethodOptions(parser, options.ExtractProperties);
      if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)
        throw kSameTerminalError;
      if (parser[NKey::kOutputDir].ThereIs)
      {
        options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
        NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
      }

      options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
      if (parser[NKey::kOverwrite].ThereIs)
        options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
      else if (options.YesToAll)
        options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
    }
  }
  else if (options.Command.IsFromUpdateGroup())
  {
    CUpdateOptions &updateOptions = options.UpdateOptions;

    SetAddCommandOptions(options.Command.CommandType, parser, updateOptions);
    
    SetMethodOptions(parser, updateOptions.MethodMode.Properties);

    if (parser[NKey::kShareForWrite].ThereIs)
      updateOptions.OpenShareForWrite = true;

    options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;

    if (options.EnablePercents)
    {
      if ((options.StdOutMode && !options.IsStdErrTerminal) ||
         (!options.StdOutMode && !options.IsStdOutTerminal))
        options.EnablePercents = false;
    }

    updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
    if (updateOptions.EMailMode)
    {
      updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
      if (updateOptions.EMailAddress.Length() > 0)
        if (updateOptions.EMailAddress[0] == L'.')
        {
          updateOptions.EMailRemoveAfter = true;
          updateOptions.EMailAddress.Delete(0);
        }
    }

    updateOptions.StdOutMode = options.StdOutMode;
    updateOptions.StdInMode = options.StdInMode;

    if (updateOptions.StdOutMode && updateOptions.EMailMode)
      throw "stdout mode and email mode cannot be combined";
    if (updateOptions.StdOutMode && options.IsStdOutTerminal)
      throw kTerminalOutError;
    if (updateOptions.StdInMode)
      updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();

    #ifdef _WIN32
    ConvertToLongNames(options.WildcardCensor);
    #endif
  }
  else if (options.Command.CommandType == NCommandType::kBenchmark)
  {
    options.NumThreads = (UInt32)-1;
    options.DictionarySize = (UInt32)-1;
    options.NumIterations = 1;
    if (curCommandIndex < numNonSwitchStrings)
    {
      if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations))
        ThrowUserErrorException();
    }
    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
    {
      UString postString = parser[NKey::kProperty].PostStrings[i];
      postString.MakeUpper();
      if (postString.Length() < 2)
        ThrowUserErrorException();
      if (postString[0] == 'D')
      {
        int pos = 1;
        if (postString[pos] == '=')
          pos++;
        UInt32 logSize;
        if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))
          ThrowUserErrorException();
        if (logSize > 31)
          ThrowUserErrorException();
        options.DictionarySize = 1 << logSize;
      }
      else if (postString[0] == 'M' && postString[1] == 'T' )
      {
        int pos = 2;
        if (postString[pos] == '=')
          pos++;
        if (postString[pos] != 0)
          if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads))
            ThrowUserErrorException();
      }
      else if (postString[0] == 'M' && postString[1] == '=' )
      {
        int pos = 2;
        if (postString[pos] != 0)
          options.Method = postString.Mid(2);
      }
      else
        ThrowUserErrorException();
    }
  }
  else if (options.Command.CommandType == NCommandType::kInfo)
  {
  }
  else
    ThrowUserErrorException();
  options.WildcardCensor.ExtendExclude();
}
void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
{
  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
  int numNonSwitchStrings = nonSwitchStrings.Size();
  if(numNonSwitchStrings < kMinNonSwitchWords)  
    ThrowUserErrorException();

  if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
    ThrowUserErrorException();

  options.TechMode = parser[NKey::kTechMode].ThereIs;

  if (parser[NKey::kCaseSensitive].ThereIs)
    g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);

  NRecursedType::EEnum recursedType;
  if (parser[NKey::kRecursed].ThereIs)
    recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
  else
    recursedType = NRecursedType::kNonRecursed;

  UINT codePage = CP_UTF8;
  if (parser[NKey::kCharSet].ThereIs)
  {
    UString name = parser[NKey::kCharSet].PostStrings.Front();
    name.MakeUpper();
    int i;
    for (i = 0; i < kNumCodePages; i++)
    {
      const CCodePagePair &pair = g_CodePagePairs[i];
      if (name.Compare(pair.Name) == 0)
      {
        codePage = pair.CodePage;
        break;
      }
    }
    if (i >= kNumCodePages)
      ThrowUserErrorException();
  }

  bool thereAreSwitchIncludes = false;
  if (parser[NKey::kInclude].ThereIs)
  {
    thereAreSwitchIncludes = true;
    AddSwitchWildCardsToCensor(options.WildcardCensor, 
        parser[NKey::kInclude].PostStrings, true, recursedType, codePage);
  }
  if (parser[NKey::kExclude].ThereIs)
    AddSwitchWildCardsToCensor(options.WildcardCensor, 
        parser[NKey::kExclude].PostStrings, false, recursedType, codePage);
 
  int curCommandIndex = kCommandIndex + 1;
  bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && 
      options.Command.CommandType != NCommandType::kBenchmark && 
      options.Command.CommandType != NCommandType::kInfo;
  if (thereIsArchiveName)
  {
    if(curCommandIndex >= numNonSwitchStrings)  
      ThrowUserErrorException();
    options.ArchiveName = nonSwitchStrings[curCommandIndex++];
  }

  AddToCensorFromNonSwitchesStrings(
      curCommandIndex, options.WildcardCensor, 
      nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);

  options.YesToAll = parser[NKey::kYes].ThereIs;

  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();

  options.PasswordEnabled = parser[NKey::kPassword].ThereIs;

  if(options.PasswordEnabled)
    options.Password = parser[NKey::kPassword].PostStrings[0];

  options.StdInMode = parser[NKey::kStdIn].ThereIs;
  options.ShowDialog = parser[NKey::kShowDialog].ThereIs;

  if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
  {
    if (options.StdInMode)
      ThrowException("Reading archives from stdin is not implemented");
    if (!options.WildcardCensor.AllAreRelative())
      ThrowException("Cannot use absolute pathnames for this command");

    NWildcard::CCensor archiveWildcardCensor;

    if (parser[NKey::kArInclude].ThereIs)
    {
      AddSwitchWildCardsToCensor(archiveWildcardCensor, 
        parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);
    }
    if (parser[NKey::kArExclude].ThereIs)
      AddSwitchWildCardsToCensor(archiveWildcardCensor, 
      parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);

    if (thereIsArchiveName)
      AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);

    #ifdef _WIN32
    ConvertToLongNames(archiveWildcardCensor);
    #endif

    archiveWildcardCensor.ExtendExclude();

    CObjectVector<CDirItem> dirItems;
    {
      UStringVector errorPaths;
      CRecordVector<DWORD> errorCodes;
      HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes);
      if (res != S_OK || errorPaths.Size() > 0)
        throw "cannot find archive";
    }
    UStringVector archivePaths;
    int i;
    for (i = 0; i < dirItems.Size(); i++)
    {
      const CDirItem &dirItem = dirItems[i];
      if (!dirItem.IsDirectory())
        archivePaths.Add(dirItem.FullPath);
    }

    if (archivePaths.Size() == 0)
      throw "there is no such archive";

    UStringVector archivePathsFull;

    for (i = 0; i < archivePaths.Size(); i++)
    {
      UString fullPath;
      NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath);
      archivePathsFull.Add(fullPath);
    }
    CIntVector indices;
    SortFileNames(archivePathsFull, indices);
    options.ArchivePathsSorted.Reserve(indices.Size());
    options.ArchivePathsFullSorted.Reserve(indices.Size());
    for (i = 0; i < indices.Size(); i++)
    {
      options.ArchivePathsSorted.Add(archivePaths[indices[i]]);
      options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]);
    }

    if (isExtractGroupCommand)
    {
      SetMethodOptions(parser, options.ExtractProperties); 
      if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)
        throw kSameTerminalError;
      if(parser[NKey::kOutputDir].ThereIs)
      {
        options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
        NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
      }

      options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
      if(parser[NKey::kOverwrite].ThereIs)
        options.OverwriteMode = 
            k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
      else if (options.YesToAll)
        options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
    }
  }
  else if(options.Command.IsFromUpdateGroup())
  {
    CUpdateOptions &updateOptions = options.UpdateOptions;

    if(parser[NKey::kArchiveType].ThereIs)
      options.ArcType = parser[NKey::kArchiveType].PostStrings[0];

    SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); 
    
    SetMethodOptions(parser, updateOptions.MethodMode.Properties); 

    if (parser[NKey::kShareForWrite].ThereIs)
      updateOptions.OpenShareForWrite = true;

    options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;

    if (options.EnablePercents)
    {
      if ((options.StdOutMode && !options.IsStdErrTerminal) || 
         (!options.StdOutMode && !options.IsStdOutTerminal))  
        options.EnablePercents = false;
    }

    updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
    if (updateOptions.EMailMode)
    {
      updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
      if (updateOptions.EMailAddress.Length() > 0)
        if (updateOptions.EMailAddress[0] == L'.')
        {
          updateOptions.EMailRemoveAfter = true;
          updateOptions.EMailAddress.Delete(0);
        }
    }

    updateOptions.StdOutMode = options.StdOutMode;
    updateOptions.StdInMode = options.StdInMode;

    if (updateOptions.StdOutMode && updateOptions.EMailMode)
      throw "stdout mode and email mode cannot be combined";
    if (updateOptions.StdOutMode && options.IsStdOutTerminal)
      throw kTerminalOutError;
    if(updateOptions.StdInMode)
      updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();

    #ifdef _WIN32
    ConvertToLongNames(options.WildcardCensor);
    #endif
  }
  else if(options.Command.CommandType == NCommandType::kBenchmark)
  {
    options.NumThreads = (UInt32)-1;
    options.DictionarySize = (UInt32)-1;
    options.NumIterations = 1;
    if (curCommandIndex < numNonSwitchStrings)  
    {
      if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations))
        ThrowUserErrorException();
    }
    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
    {
      UString postString = parser[NKey::kProperty].PostStrings[i];
      postString.MakeUpper();
      if (postString.Length() < 2)
        ThrowUserErrorException();
      if (postString[0] == 'D')
      {
        int pos = 1;
        if (postString[pos] == '=')
          pos++;
        UInt32 logSize;
        if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))
          ThrowUserErrorException();
        if (logSize > 31)
          ThrowUserErrorException();
        options.DictionarySize = 1 << logSize;
      }
      else if (postString[0] == 'M' && postString[1] == 'T' )
      {
        int pos = 2;
        if (postString[pos] == '=')
          pos++;
        if (postString[pos] != 0)
          if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads))
            ThrowUserErrorException();
      }
      else if (postString[0] == 'M' && postString[1] == '=' )
      {
        int pos = 2;
        if (postString[pos] != 0)
          options.Method = postString.Mid(2);
      }
      else
        ThrowUserErrorException();
    }
  }
  else if(options.Command.CommandType == NCommandType::kInfo)
  {
  }
  else 
    ThrowUserErrorException();
  options.WildcardCensor.ExtendExclude();
}