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