1// CommandLineParser.cpp 2 3#include "StdAfx.h" 4 5#include "CommandLineParser.h" 6 7static 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 (MyCharLower_Ascii(c) != MyCharLower_Ascii(*u)) 15 return false; 16 a++; 17 u++; 18 } 19} 20 21namespace NCommandLineParser { 22 23bool 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 45void 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 62static const char *kStopSwitchParsing = "--"; 63 64static bool inline IsItSwitchChar(wchar_t c) 65{ 66 return (c == '-'); 67} 68 69CParser::CParser(unsigned numSwitches): 70 _numSwitches(numSwitches), 71 _switches(0) 72{ 73 _switches = new CSwitchResult[numSwitches]; 74} 75 76CParser::~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 84bool 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 != 0) 139 { 140 sw.WithMinus = (s[pos] == '-'); 141 if (sw.WithMinus) 142 pos++; 143 } 144 break; 145 146 case NSwitchType::kChar: 147 if (rem != 0) 148 { 149 wchar_t c = s[pos]; 150 if (c <= 0x7F) 151 { 152 sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); 153 if (sw.PostCharIndex >= 0) 154 pos++; 155 } 156 } 157 break; 158 159 case NSwitchType::kString: 160 sw.PostStrings.Add((const wchar_t *)s + pos); 161 return true; 162 } 163 if (pos != s.Len()) 164 { 165 ErrorMessage = "Too long switch:"; 166 return false; 167 } 168 return true; 169} 170 171bool CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) 172{ 173 ErrorLine.Empty(); 174 bool stopSwitch = false; 175 FOR_VECTOR (i, commandStrings) 176 { 177 const UString &s = commandStrings[i]; 178 if (!stopSwitch) 179 { 180 if (s.IsEqualTo(kStopSwitchParsing)) 181 { 182 stopSwitch = true; 183 continue; 184 } 185 if (!s.IsEmpty() && IsItSwitchChar(s[0])) 186 { 187 if (ParseString(s, switchForms)) 188 continue; 189 ErrorLine = s; 190 return false; 191 } 192 } 193 NonSwitchStrings.Add(s); 194 } 195 return true; 196} 197 198} 199