1 // CommandLineParser.cpp 2 3 #include "StdAfx.h" 4 5 #include "CommandLineParser.h" 6 7 static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a) 8 { 9 for (;;) 10 { 11 char c = *a; 12 if (c == 0) 13 return true; 14 if ((unsigned char)MyCharLower_Ascii(c) != MyCharLower_Ascii(*u)) 15 return false; 16 a++; 17 u++; 18 } 19 } 20 21 namespace NCommandLineParser { 22 23 bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) 24 { 25 dest1.Empty(); 26 dest2.Empty(); 27 bool quoteMode = false; 28 unsigned i; 29 for (i = 0; i < src.Len(); i++) 30 { 31 wchar_t c = src[i]; 32 if ((c == L' ' || c == L'\t') && !quoteMode) 33 { 34 dest2 = src.Ptr(i + 1); 35 return i != 0; 36 } 37 if (c == L'\"') 38 quoteMode = !quoteMode; 39 else 40 dest1 += c; 41 } 42 return i != 0; 43 } 44 45 void SplitCommandLine(const UString &s, UStringVector &parts) 46 { 47 UString sTemp = s; 48 sTemp.Trim(); 49 parts.Clear(); 50 for (;;) 51 { 52 UString s1, s2; 53 if (SplitCommandLine(sTemp, s1, s2)) 54 parts.Add(s1); 55 if (s2.IsEmpty()) 56 break; 57 sTemp = s2; 58 } 59 } 60 61 62 static const char *kStopSwitchParsing = "--"; 63 64 static bool inline IsItSwitchChar(wchar_t c) 65 { 66 return (c == '-'); 67 } 68 69 CParser::CParser(unsigned numSwitches): 70 _numSwitches(numSwitches), 71 _switches(0) 72 { 73 _switches = new CSwitchResult[numSwitches]; 74 } 75 76 CParser::~CParser() 77 { 78 delete []_switches; 79 } 80 81 82 // if (s) contains switch then function updates switch structures 83 // out: true, if (s) is a switch 84 bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) 85 { 86 if (s.IsEmpty() || !IsItSwitchChar(s[0])) 87 return false; 88 89 unsigned pos = 1; 90 unsigned switchIndex = 0; 91 int maxLen = -1; 92 93 for (unsigned i = 0; i < _numSwitches; i++) 94 { 95 const char *key = switchForms[i].Key; 96 unsigned switchLen = MyStringLen(key); 97 if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) 98 continue; 99 if (IsString1PrefixedByString2_NoCase((const wchar_t *)s + pos, key)) 100 { 101 switchIndex = i; 102 maxLen = switchLen; 103 } 104 } 105 106 if (maxLen < 0) 107 { 108 ErrorMessage = "Unknown switch:"; 109 return false; 110 } 111 112 pos += maxLen; 113 114 CSwitchResult &sw = _switches[switchIndex]; 115 const CSwitchForm &form = switchForms[switchIndex]; 116 117 if (!form.Multi && sw.ThereIs) 118 { 119 ErrorMessage = "Multiple instances for switch:"; 120 return false; 121 } 122 123 sw.ThereIs = true; 124 125 int rem = s.Len() - pos; 126 if (rem < form.MinLen) 127 { 128 ErrorMessage = "Too short switch:"; 129 return false; 130 } 131 132 sw.WithMinus = false; 133 sw.PostCharIndex = -1; 134 135 switch (form.Type) 136 { 137 case NSwitchType::kMinus: 138 if (rem == 1) 139 { 140 sw.WithMinus = (s[pos] == '-'); 141 if (sw.WithMinus) 142 return true; 143 ErrorMessage = "Incorrect switch postfix:"; 144 return false; 145 } 146 break; 147 148 case NSwitchType::kChar: 149 if (rem == 1) 150 { 151 wchar_t c = s[pos]; 152 if (c <= 0x7F) 153 { 154 sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); 155 if (sw.PostCharIndex >= 0) 156 return true; 157 } 158 ErrorMessage = "Incorrect switch postfix:"; 159 return false; 160 } 161 break; 162 163 case NSwitchType::kString: 164 sw.PostStrings.Add((const wchar_t *)s + pos); 165 return true; 166 } 167 168 if (pos != s.Len()) 169 { 170 ErrorMessage = "Too long switch:"; 171 return false; 172 } 173 return true; 174 } 175 176 bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) 177 { 178 ErrorLine.Empty(); 179 bool stopSwitch = false; 180 FOR_VECTOR (i, commandStrings) 181 { 182 const UString &s = commandStrings[i]; 183 if (!stopSwitch) 184 { 185 if (s.IsEqualTo(kStopSwitchParsing)) 186 { 187 stopSwitch = true; 188 continue; 189 } 190 if (!s.IsEmpty() && IsItSwitchChar(s[0])) 191 { 192 if (ParseString(s, switchForms)) 193 continue; 194 ErrorLine = s; 195 return false; 196 } 197 } 198 NonSwitchStrings.Add(s); 199 } 200 return true; 201 } 202 203 } 204