1370b324cSopenharmony_ci// CommandLineParser.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "CommandLineParser.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_cinamespace NCommandLineParser {
8370b324cSopenharmony_ci
9370b324cSopenharmony_cibool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
10370b324cSopenharmony_ci{
11370b324cSopenharmony_ci  dest1.Empty();
12370b324cSopenharmony_ci  dest2.Empty();
13370b324cSopenharmony_ci  bool quoteMode = false;
14370b324cSopenharmony_ci  unsigned i;
15370b324cSopenharmony_ci  for (i = 0; i < src.Len(); i++)
16370b324cSopenharmony_ci  {
17370b324cSopenharmony_ci    wchar_t c = src[i];
18370b324cSopenharmony_ci    if ((c == L' ' || c == L'\t') && !quoteMode)
19370b324cSopenharmony_ci    {
20370b324cSopenharmony_ci      dest2 = src.Ptr(i + 1);
21370b324cSopenharmony_ci      return i != 0;
22370b324cSopenharmony_ci    }
23370b324cSopenharmony_ci    if (c == L'\"')
24370b324cSopenharmony_ci      quoteMode = !quoteMode;
25370b324cSopenharmony_ci    else
26370b324cSopenharmony_ci      dest1 += c;
27370b324cSopenharmony_ci  }
28370b324cSopenharmony_ci  return i != 0;
29370b324cSopenharmony_ci}
30370b324cSopenharmony_ci
31370b324cSopenharmony_civoid SplitCommandLine(const UString &s, UStringVector &parts)
32370b324cSopenharmony_ci{
33370b324cSopenharmony_ci  UString sTemp (s);
34370b324cSopenharmony_ci  sTemp.Trim();
35370b324cSopenharmony_ci  parts.Clear();
36370b324cSopenharmony_ci  for (;;)
37370b324cSopenharmony_ci  {
38370b324cSopenharmony_ci    UString s1, s2;
39370b324cSopenharmony_ci    if (SplitCommandLine(sTemp, s1, s2))
40370b324cSopenharmony_ci      parts.Add(s1);
41370b324cSopenharmony_ci    if (s2.IsEmpty())
42370b324cSopenharmony_ci      break;
43370b324cSopenharmony_ci    sTemp = s2;
44370b324cSopenharmony_ci  }
45370b324cSopenharmony_ci}
46370b324cSopenharmony_ci
47370b324cSopenharmony_ci
48370b324cSopenharmony_cistatic const char * const kStopSwitchParsing = "--";
49370b324cSopenharmony_ci
50370b324cSopenharmony_cistatic bool inline IsItSwitchChar(wchar_t c)
51370b324cSopenharmony_ci{
52370b324cSopenharmony_ci  return (c == '-');
53370b324cSopenharmony_ci}
54370b324cSopenharmony_ci
55370b324cSopenharmony_ciCParser::CParser():
56370b324cSopenharmony_ci  _switches(NULL),
57370b324cSopenharmony_ci  StopSwitchIndex(-1)
58370b324cSopenharmony_ci{
59370b324cSopenharmony_ci}
60370b324cSopenharmony_ci
61370b324cSopenharmony_ciCParser::~CParser()
62370b324cSopenharmony_ci{
63370b324cSopenharmony_ci  delete []_switches;
64370b324cSopenharmony_ci}
65370b324cSopenharmony_ci
66370b324cSopenharmony_ci
67370b324cSopenharmony_ci// if (s) contains switch then function updates switch structures
68370b324cSopenharmony_ci// out: true, if (s) is a switch
69370b324cSopenharmony_cibool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches)
70370b324cSopenharmony_ci{
71370b324cSopenharmony_ci  if (s.IsEmpty() || !IsItSwitchChar(s[0]))
72370b324cSopenharmony_ci    return false;
73370b324cSopenharmony_ci
74370b324cSopenharmony_ci  unsigned pos = 1;
75370b324cSopenharmony_ci  unsigned switchIndex = 0;
76370b324cSopenharmony_ci  int maxLen = -1;
77370b324cSopenharmony_ci
78370b324cSopenharmony_ci  for (unsigned i = 0; i < numSwitches; i++)
79370b324cSopenharmony_ci  {
80370b324cSopenharmony_ci    const char * const key = switchForms[i].Key;
81370b324cSopenharmony_ci    unsigned switchLen = MyStringLen(key);
82370b324cSopenharmony_ci    if ((int)switchLen <= maxLen || pos + switchLen > s.Len())
83370b324cSopenharmony_ci      continue;
84370b324cSopenharmony_ci    if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key))
85370b324cSopenharmony_ci    {
86370b324cSopenharmony_ci      switchIndex = i;
87370b324cSopenharmony_ci      maxLen = (int)switchLen;
88370b324cSopenharmony_ci    }
89370b324cSopenharmony_ci  }
90370b324cSopenharmony_ci
91370b324cSopenharmony_ci  if (maxLen < 0)
92370b324cSopenharmony_ci  {
93370b324cSopenharmony_ci    ErrorMessage = "Unknown switch:";
94370b324cSopenharmony_ci    return false;
95370b324cSopenharmony_ci  }
96370b324cSopenharmony_ci
97370b324cSopenharmony_ci  pos += (unsigned)maxLen;
98370b324cSopenharmony_ci
99370b324cSopenharmony_ci  CSwitchResult &sw = _switches[switchIndex];
100370b324cSopenharmony_ci  const CSwitchForm &form = switchForms[switchIndex];
101370b324cSopenharmony_ci
102370b324cSopenharmony_ci  if (!form.Multi && sw.ThereIs)
103370b324cSopenharmony_ci  {
104370b324cSopenharmony_ci    ErrorMessage = "Multiple instances for switch:";
105370b324cSopenharmony_ci    return false;
106370b324cSopenharmony_ci  }
107370b324cSopenharmony_ci
108370b324cSopenharmony_ci  sw.ThereIs = true;
109370b324cSopenharmony_ci
110370b324cSopenharmony_ci  const unsigned rem = s.Len() - pos;
111370b324cSopenharmony_ci  if (rem < form.MinLen)
112370b324cSopenharmony_ci  {
113370b324cSopenharmony_ci    ErrorMessage = "Too short switch:";
114370b324cSopenharmony_ci    return false;
115370b324cSopenharmony_ci  }
116370b324cSopenharmony_ci
117370b324cSopenharmony_ci  sw.WithMinus = false;
118370b324cSopenharmony_ci  sw.PostCharIndex = -1;
119370b324cSopenharmony_ci
120370b324cSopenharmony_ci  switch (form.Type)
121370b324cSopenharmony_ci  {
122370b324cSopenharmony_ci    case NSwitchType::kMinus:
123370b324cSopenharmony_ci      if (rem == 1)
124370b324cSopenharmony_ci      {
125370b324cSopenharmony_ci        sw.WithMinus = (s[pos] == '-');
126370b324cSopenharmony_ci        if (sw.WithMinus)
127370b324cSopenharmony_ci          return true;
128370b324cSopenharmony_ci        ErrorMessage = "Incorrect switch postfix:";
129370b324cSopenharmony_ci        return false;
130370b324cSopenharmony_ci      }
131370b324cSopenharmony_ci      break;
132370b324cSopenharmony_ci
133370b324cSopenharmony_ci    case NSwitchType::kChar:
134370b324cSopenharmony_ci      if (rem == 1)
135370b324cSopenharmony_ci      {
136370b324cSopenharmony_ci        wchar_t c = s[pos];
137370b324cSopenharmony_ci        if (c <= 0x7F)
138370b324cSopenharmony_ci        {
139370b324cSopenharmony_ci          sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
140370b324cSopenharmony_ci          if (sw.PostCharIndex >= 0)
141370b324cSopenharmony_ci            return true;
142370b324cSopenharmony_ci        }
143370b324cSopenharmony_ci        ErrorMessage = "Incorrect switch postfix:";
144370b324cSopenharmony_ci        return false;
145370b324cSopenharmony_ci      }
146370b324cSopenharmony_ci      break;
147370b324cSopenharmony_ci
148370b324cSopenharmony_ci    case NSwitchType::kString:
149370b324cSopenharmony_ci    {
150370b324cSopenharmony_ci      sw.PostStrings.Add(s.Ptr(pos));
151370b324cSopenharmony_ci      return true;
152370b324cSopenharmony_ci    }
153370b324cSopenharmony_ci  }
154370b324cSopenharmony_ci
155370b324cSopenharmony_ci  if (pos != s.Len())
156370b324cSopenharmony_ci  {
157370b324cSopenharmony_ci    ErrorMessage = "Too long switch:";
158370b324cSopenharmony_ci    return false;
159370b324cSopenharmony_ci  }
160370b324cSopenharmony_ci  return true;
161370b324cSopenharmony_ci}
162370b324cSopenharmony_ci
163370b324cSopenharmony_ci
164370b324cSopenharmony_cibool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings)
165370b324cSopenharmony_ci{
166370b324cSopenharmony_ci  StopSwitchIndex = -1;
167370b324cSopenharmony_ci  ErrorMessage.Empty();
168370b324cSopenharmony_ci  ErrorLine.Empty();
169370b324cSopenharmony_ci  NonSwitchStrings.Clear();
170370b324cSopenharmony_ci  delete []_switches;
171370b324cSopenharmony_ci  _switches = NULL;
172370b324cSopenharmony_ci  _switches = new CSwitchResult[numSwitches];
173370b324cSopenharmony_ci
174370b324cSopenharmony_ci  FOR_VECTOR (i, commandStrings)
175370b324cSopenharmony_ci  {
176370b324cSopenharmony_ci    const UString &s = commandStrings[i];
177370b324cSopenharmony_ci    if (StopSwitchIndex < 0)
178370b324cSopenharmony_ci    {
179370b324cSopenharmony_ci      if (s.IsEqualTo(kStopSwitchParsing))
180370b324cSopenharmony_ci      {
181370b324cSopenharmony_ci        StopSwitchIndex = (int)NonSwitchStrings.Size();
182370b324cSopenharmony_ci        continue;
183370b324cSopenharmony_ci      }
184370b324cSopenharmony_ci      if (!s.IsEmpty() && IsItSwitchChar(s[0]))
185370b324cSopenharmony_ci      {
186370b324cSopenharmony_ci        if (ParseString(s, switchForms, numSwitches))
187370b324cSopenharmony_ci          continue;
188370b324cSopenharmony_ci        ErrorLine = s;
189370b324cSopenharmony_ci        return false;
190370b324cSopenharmony_ci      }
191370b324cSopenharmony_ci    }
192370b324cSopenharmony_ci    NonSwitchStrings.Add(s);
193370b324cSopenharmony_ci  }
194370b324cSopenharmony_ci  return true;
195370b324cSopenharmony_ci}
196370b324cSopenharmony_ci
197370b324cSopenharmony_ci}
198