michael@0: // CommandLineParser.cpp michael@0: michael@0: #include "StdAfx.h" michael@0: michael@0: #include "CommandLineParser.h" michael@0: michael@0: namespace NCommandLineParser { michael@0: michael@0: void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) michael@0: { michael@0: dest1.Empty(); michael@0: dest2.Empty(); michael@0: bool quoteMode = false; michael@0: int i; michael@0: for (i = 0; i < src.Length(); i++) michael@0: { michael@0: wchar_t c = src[i]; michael@0: if (c == L'\"') michael@0: quoteMode = !quoteMode; michael@0: else if (c == L' ' && !quoteMode) michael@0: { michael@0: i++; michael@0: break; michael@0: } michael@0: else michael@0: dest1 += c; michael@0: } michael@0: dest2 = src.Mid(i); michael@0: } michael@0: michael@0: void SplitCommandLine(const UString &s, UStringVector &parts) michael@0: { michael@0: UString sTemp = s; michael@0: sTemp.Trim(); michael@0: parts.Clear(); michael@0: while (true) michael@0: { michael@0: UString s1, s2; michael@0: SplitCommandLine(sTemp, s1, s2); michael@0: // s1.Trim(); michael@0: // s2.Trim(); michael@0: if (!s1.IsEmpty()) michael@0: parts.Add(s1); michael@0: if (s2.IsEmpty()) michael@0: return; michael@0: sTemp = s2; michael@0: } michael@0: } michael@0: michael@0: michael@0: static const wchar_t kSwitchID1 = '-'; michael@0: // static const wchar_t kSwitchID2 = '/'; michael@0: michael@0: static const wchar_t kSwitchMinus = '-'; michael@0: static const wchar_t *kStopSwitchParsing = L"--"; michael@0: michael@0: static bool IsItSwitchChar(wchar_t c) michael@0: { michael@0: return (c == kSwitchID1 /*|| c == kSwitchID2 */); michael@0: } michael@0: michael@0: CParser::CParser(int numSwitches): michael@0: _numSwitches(numSwitches) michael@0: { michael@0: _switches = new CSwitchResult[_numSwitches]; michael@0: } michael@0: michael@0: CParser::~CParser() michael@0: { michael@0: delete []_switches; michael@0: } michael@0: michael@0: void CParser::ParseStrings(const CSwitchForm *switchForms, michael@0: const UStringVector &commandStrings) michael@0: { michael@0: int numCommandStrings = commandStrings.Size(); michael@0: bool stopSwitch = false; michael@0: for (int i = 0; i < numCommandStrings; i++) michael@0: { michael@0: const UString &s = commandStrings[i]; michael@0: if (stopSwitch) michael@0: NonSwitchStrings.Add(s); michael@0: else michael@0: if (s == kStopSwitchParsing) michael@0: stopSwitch = true; michael@0: else michael@0: if (!ParseString(s, switchForms)) michael@0: NonSwitchStrings.Add(s); michael@0: } michael@0: } michael@0: michael@0: // if string contains switch then function updates switch structures michael@0: // out: (string is a switch) michael@0: bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) michael@0: { michael@0: int len = s.Length(); michael@0: if (len == 0) michael@0: return false; michael@0: int pos = 0; michael@0: if (!IsItSwitchChar(s[pos])) michael@0: return false; michael@0: while(pos < len) michael@0: { michael@0: if (IsItSwitchChar(s[pos])) michael@0: pos++; michael@0: const int kNoLen = -1; michael@0: int matchedSwitchIndex = 0; // GCC Warning michael@0: int maxLen = kNoLen; michael@0: for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) michael@0: { michael@0: int switchLen = MyStringLen(switchForms[switchIndex].IDString); michael@0: if (switchLen <= maxLen || pos + switchLen > len) michael@0: continue; michael@0: michael@0: UString temp = s + pos; michael@0: temp = temp.Left(switchLen); michael@0: if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) michael@0: // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) michael@0: { michael@0: matchedSwitchIndex = switchIndex; michael@0: maxLen = switchLen; michael@0: } michael@0: } michael@0: if (maxLen == kNoLen) michael@0: throw "maxLen == kNoLen"; michael@0: CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; michael@0: const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; michael@0: if ((!switchForm.Multi) && matchedSwitch.ThereIs) michael@0: throw "switch must be single"; michael@0: matchedSwitch.ThereIs = true; michael@0: pos += maxLen; michael@0: int tailSize = len - pos; michael@0: NSwitchType::EEnum type = switchForm.Type; michael@0: switch(type) michael@0: { michael@0: case NSwitchType::kPostMinus: michael@0: { michael@0: if (tailSize == 0) michael@0: matchedSwitch.WithMinus = false; michael@0: else michael@0: { michael@0: matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); michael@0: if (matchedSwitch.WithMinus) michael@0: pos++; michael@0: } michael@0: break; michael@0: } michael@0: case NSwitchType::kPostChar: michael@0: { michael@0: if (tailSize < switchForm.MinLen) michael@0: throw "switch is not full"; michael@0: UString set = switchForm.PostCharSet; michael@0: const int kEmptyCharValue = -1; michael@0: if (tailSize == 0) michael@0: matchedSwitch.PostCharIndex = kEmptyCharValue; michael@0: else michael@0: { michael@0: int index = set.Find(s[pos]); michael@0: if (index < 0) michael@0: matchedSwitch.PostCharIndex = kEmptyCharValue; michael@0: else michael@0: { michael@0: matchedSwitch.PostCharIndex = index; michael@0: pos++; michael@0: } michael@0: } michael@0: break; michael@0: } michael@0: case NSwitchType::kLimitedPostString: michael@0: case NSwitchType::kUnLimitedPostString: michael@0: { michael@0: int minLen = switchForm.MinLen; michael@0: if (tailSize < minLen) michael@0: throw "switch is not full"; michael@0: if (type == NSwitchType::kUnLimitedPostString) michael@0: { michael@0: matchedSwitch.PostStrings.Add(s.Mid(pos)); michael@0: return true; michael@0: } michael@0: int maxLen = switchForm.MaxLen; michael@0: UString stringSwitch = s.Mid(pos, minLen); michael@0: pos += minLen; michael@0: for(int i = minLen; i < maxLen && pos < len; i++, pos++) michael@0: { michael@0: wchar_t c = s[pos]; michael@0: if (IsItSwitchChar(c)) michael@0: break; michael@0: stringSwitch += c; michael@0: } michael@0: matchedSwitch.PostStrings.Add(stringSwitch); michael@0: break; michael@0: } michael@0: case NSwitchType::kSimple: michael@0: break; michael@0: } michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: const CSwitchResult& CParser::operator[](size_t index) const michael@0: { michael@0: return _switches[index]; michael@0: } michael@0: michael@0: ///////////////////////////////// michael@0: // Command parsing procedures michael@0: michael@0: int ParseCommand(int numCommandForms, const CCommandForm *commandForms, michael@0: const UString &commandString, UString &postString) michael@0: { michael@0: for(int i = 0; i < numCommandForms; i++) michael@0: { michael@0: const UString id = commandForms[i].IDString; michael@0: if (commandForms[i].PostStringMode) michael@0: { michael@0: if(commandString.Find(id) == 0) michael@0: { michael@0: postString = commandString.Mid(id.Length()); michael@0: return i; michael@0: } michael@0: } michael@0: else michael@0: if (commandString == id) michael@0: { michael@0: postString.Empty(); michael@0: return i; michael@0: } michael@0: } michael@0: return -1; michael@0: } michael@0: michael@0: }