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