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