1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// CommandLineParser.cpp 2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h" 4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "CommandLineParser.h" 6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 7baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace NCommandLineParser { 8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 9baa3858d3f5d128a5c8466b700098109edcad5f2repo syncbool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) 10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync dest1.Empty(); 12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync dest2.Empty(); 13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync bool quoteMode = false; 14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int i; 15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (i = 0; i < src.Length(); i++) 16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync wchar_t c = src[i]; 18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (c == L' ' && !quoteMode) 19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync dest2 = src.Mid(i + 1); 21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return i != 0; 22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (c == L'\"') 24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync quoteMode = !quoteMode; 25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync dest1 += c; 27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return i != 0; 29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 31baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid SplitCommandLine(const UString &s, UStringVector &parts) 32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UString sTemp = s; 34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync sTemp.Trim(); 35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync parts.Clear(); 36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (;;) 37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UString s1, s2; 39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (SplitCommandLine(sTemp, s1, s2)) 40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync parts.Add(s1); 41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (s2.IsEmpty()) 42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync sTemp = s2; 44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 48baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const wchar_t kSwitchID1 = '-'; 49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// static const wchar_t kSwitchID2 = '/'; 50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 51baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const wchar_t kSwitchMinus = '-'; 52baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const wchar_t *kStopSwitchParsing = L"--"; 53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 54baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic bool IsItSwitchChar(wchar_t c) 55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return (c == kSwitchID1 /*|| c == kSwitchID2 */); 57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 59baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCParser::CParser(int numSwitches): 60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync _numSwitches(numSwitches) 61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync _switches = new CSwitchResult[_numSwitches]; 63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 65baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCParser::~CParser() 66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync delete []_switches; 68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 70baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CParser::ParseStrings(const CSwitchForm *switchForms, 71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const UStringVector &commandStrings) 72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int numCommandStrings = commandStrings.Size(); 74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync bool stopSwitch = false; 75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (int i = 0; i < numCommandStrings; i++) 76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const UString &s = commandStrings[i]; 78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (stopSwitch) 79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync NonSwitchStrings.Add(s); 80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (s == kStopSwitchParsing) 82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync stopSwitch = true; 83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (!ParseString(s, switchForms)) 85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync NonSwitchStrings.Add(s); 86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// if string contains switch then function updates switch structures 90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// out: (string is a switch) 91baa3858d3f5d128a5c8466b700098109edcad5f2repo syncbool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) 92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int len = s.Length(); 94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (len == 0) 95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return false; 96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int pos = 0; 97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (!IsItSwitchChar(s[pos])) 98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return false; 99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (pos < len) 100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (IsItSwitchChar(s[pos])) 102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync pos++; 103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const int kNoLen = -1; 104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int matchedSwitchIndex = 0; // GCC Warning 105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int maxLen = kNoLen; 106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) 107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int switchLen = MyStringLen(switchForms[switchIndex].IDString); 109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (switchLen <= maxLen || pos + switchLen > len) 110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync continue; 111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UString temp = s + pos; 113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync temp = temp.Left(switchLen); 114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) 115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) 116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitchIndex = switchIndex; 118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync maxLen = switchLen; 119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (maxLen == kNoLen) 122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync throw "maxLen == kNoLen"; 123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; 124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; 125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if ((!switchForm.Multi) && matchedSwitch.ThereIs) 126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync throw "switch must be single"; 127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitch.ThereIs = true; 128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync pos += maxLen; 129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int tailSize = len - pos; 130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync NSwitchType::EEnum type = switchForm.Type; 131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync switch(type) 132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync case NSwitchType::kPostMinus: 134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (tailSize == 0) 136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitch.WithMinus = false; 137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); 140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (matchedSwitch.WithMinus) 141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync pos++; 142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync case NSwitchType::kPostChar: 146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (tailSize < switchForm.MinLen) 148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync throw "switch is not full"; 149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UString set = switchForm.PostCharSet; 150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const int kEmptyCharValue = -1; 151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (tailSize == 0) 152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitch.PostCharIndex = kEmptyCharValue; 153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int index = set.Find(s[pos]); 156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (index < 0) 157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitch.PostCharIndex = kEmptyCharValue; 158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitch.PostCharIndex = index; 161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync pos++; 162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync case NSwitchType::kLimitedPostString: 167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync case NSwitchType::kUnLimitedPostString: 168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int minLen = switchForm.MinLen; 170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (tailSize < minLen) 171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync throw "switch is not full"; 172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (type == NSwitchType::kUnLimitedPostString) 173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitch.PostStrings.Add(s.Mid(pos)); 175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return true; 176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync int maxLen = switchForm.MaxLen; 178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UString stringSwitch = s.Mid(pos, minLen); 179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync pos += minLen; 180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (int i = minLen; i < maxLen && pos < len; i++, pos++) 181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync wchar_t c = s[pos]; 183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (IsItSwitchChar(c)) 184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync stringSwitch += c; 186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync matchedSwitch.PostStrings.Add(stringSwitch); 188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync case NSwitchType::kSimple: 191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return true; 195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 197baa3858d3f5d128a5c8466b700098109edcad5f2repo syncconst CSwitchResult& CParser::operator[](size_t index) const 198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return _switches[index]; 200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync///////////////////////////////// 203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// Command parsing procedures 204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 205baa3858d3f5d128a5c8466b700098109edcad5f2repo syncint ParseCommand(int numCommandForms, const CCommandForm *commandForms, 206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const UString &commandString, UString &postString) 207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (int i = 0; i < numCommandForms; i++) 209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const UString id = commandForms[i].IDString; 211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (commandForms[i].PostStringMode) 212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (commandString.Find(id) == 0) 214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync postString = commandString.Mid(id.Length()); 216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return i; 217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (commandString == id) 221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync postString.Empty(); 223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return i; 224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return -1; 227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 230