@@ -162,7 +162,7 @@ void ImportProject::FileSettings::setIncludePaths(const std::string &basepath, c
162162 continue ;
163163 if (it.compare (0 ,2 ," %(" )==0 )
164164 continue ;
165- std::string s (Path::removeQuotationMarks ( Path:: fromNativeSeparators (it) ));
165+ std::string s (Path::fromNativeSeparators (it));
166166 if (s[0 ] == ' /' || (s.size () > 1U && s.compare (1 ,2 ," :/" ) == 0 )) {
167167 if (!endsWith (s,' /' ))
168168 s += ' /' ;
@@ -217,141 +217,154 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
217217 return ImportProject::Type::UNKNOWN ;
218218}
219219
220- static std::string readUntil (const std::string& command, std::string::size_type* pos, const char until[], bool skipBackSlash = true )
220+ static std::string readUntil (const std::string & command, std::string::size_type * pos, const char until[])
221221{
222222 std::string ret;
223223 bool str = false ;
224- while (*pos < command.size () && (str || !std::strchr (until, command[*pos]))) {
225- if (skipBackSlash && command[*pos] == ' \\ ' )
226- ++* pos;
227- if (*pos < command.size ())
228- ret += command[(*pos)++];
229- if (endsWith (ret, ' \" ' ))
230- str = !str;
231- }
232- return ret;
233- }
234-
235- static void skip_whitespaces (const std::string& command, std::string::size_type *pos)
236- {
237- while (*pos < command.size () && command[*pos] == ' ' )
238- (*pos)++;
239- }
240-
241-
242- static std::string parseTillNextCommandOpt (const std::string& singleCharOpts, const std::string& command, std::string::size_type *pos)
243- {
244- std::string ret;
245- *pos = command.find_first_not_of (" /-" , *pos);
246-
247- if (*pos >= command.size ())
248- return ret;
249-
250- const char F = command[*pos];
251- if (std::strchr (singleCharOpts.c_str (), F)) {
252- (*pos)++;
253- return std::string{F};
224+ bool escape = false ;
225+ for (; *pos < command.size () && (str || !std::strchr (until, command[*pos])); (*pos)++) {
226+ if (escape) {
227+ escape = false ;
228+ if (!std::strchr (" \\\"\' " , command[*pos]))
229+ ret += ' \\ ' ;
230+ ret += command[*pos];
231+ } else if (str && command[*pos] == ' \\ ' )
232+ escape = true ;
233+ else {
234+ if (command[*pos] == ' \" ' )
235+ str = !str;
236+ ret += command[*pos];
237+ }
254238 }
255-
256- ret = readUntil (command, pos, " =" );
257239 return ret;
258240}
259241
260- void ImportProject::FileSettings::parseCommandStd (const std::string& command, std::string::size_type *pos, std::string& defs)
261- {
262- std::string def{};
263- const std::string stdval = readUntil (command, pos, " " );
264- standard = stdval;
265- if (standard.compare (0 , 3 , " c++" ) || standard.compare (0 , 5 , " gnu++" )) {
266- std::string stddef;
267- if (standard == " c++98" || standard == " gnu++98" || standard == " c++03" || standard == " gnu++03" ) {
268- stddef = " 199711L" ;
269- } else if (standard == " c++11" || standard == " gnu++11" || standard == " c++0x" || standard == " gnu++0x" ) {
270- stddef = " 201103L" ;
271- } else if (standard == " c++14" || standard == " gnu++14" || standard == " c++1y" || standard == " gnu++1y" ) {
272- stddef = " 201402L" ;
273- } else if (standard == " c++17" || standard == " gnu++17" || standard == " c++1z" || standard == " gnu++1z" ) {
274- stddef = " 201703L" ;
275- }
276-
277- if (stddef.empty ()) {
278- // TODO: log error
279- } else {
280- def += " __cplusplus=" ;
281- def += stddef;
282- def += " ;" ;
283- }
242+ static std::string unescape (const std::string &in) {
243+ std::string out;
244+ bool escape = false ;
245+ for (char c: in) {
246+ if (escape) {
247+ escape = false ;
248+ out += c;
249+ } else if (c == ' \\ ' )
250+ escape = true ;
251+ else
252+ out += c;
284253 }
285- defs += def ;
254+ return out ;
286255}
287256
288- void ImportProject::FileSettings::parseCommandDefine ( const std::string& command, std::string::size_type *pos, std::string& defs )
257+ void ImportProject::FileSettings::parseCommand ( std::string command)
289258{
290- const bool skipBackSlash = false ;
291- defs += readUntil (command, pos, " =" );
292- const std::string defval = readUntil (command, pos, " " , skipBackSlash);
293- if (!defval.empty ())
294- defs += defval;
295- defs += ' ;' ;
296- }
297-
298- void ImportProject::FileSettings::parseCommandUndefine (const std::string& command, std::string::size_type *pos)
299- {
300- const std::string fval = readUntil (command, pos, " " );
301- undefs.insert (fval);
302- }
303-
304- void ImportProject::FileSettings::parseCommandInclude (const std::string& command, std::string::size_type *pos)
305- {
306- const bool skipBackSlash = false ;
307- const std::string fval = readUntil (command, pos, " " , skipBackSlash);
308- if (std::find (includePaths.begin (), includePaths.end (), fval) == includePaths.end ())
309- includePaths.push_back (fval);
310- }
311-
312- void ImportProject::FileSettings::parseCommandSystemInclude (const std::string& command, std::string::size_type *pos)
313- {
314- const bool skipBackSlash = false ;
315- const std::string isystem = Path::removeQuotationMarks (readUntil (command, pos, " " , skipBackSlash));
316- systemIncludePaths.push_back (isystem);
317- }
318-
319- void ImportProject::FileSettings::parseCommand (const std::string &command)
320- {
321- const std::string singleCharCommandOpts = " DUI" ;
322259 std::string defs;
323260
261+ command = unescape (command);
262+
263+ // Parse command..
324264 std::string::size_type pos = 0 ;
325265 while (std::string::npos != (pos = command.find (' ' ,pos))) {
326- skip_whitespaces (command, &pos);
266+ while (pos < command.size () && command[pos] == ' ' )
267+ pos++;
327268 if (pos >= command.size ())
328269 break ;
329-
330- const auto opt = parseTillNextCommandOpt (singleCharCommandOpts, command, &pos) ;
331-
270+ if (command[pos] != ' / ' && command[pos] != ' - ' )
271+ continue ;
272+ pos++;
332273 if (pos >= command.size ())
333274 break ;
275+ const char F = command[pos++];
276+ if (std::strchr (" DUI" , F)) {
277+ while (pos < command.size () && command[pos] == ' ' )
278+ ++pos;
279+ }
280+ const std::string fval = readUntil (command, &pos, " =" );
281+ if (F==' D' ) {
282+ const std::string defval = readUntil (command, &pos, " " );
283+ defs += fval;
284+ if (!defval.empty ())
285+ defs += defval;
286+ defs += ' ;' ;
287+ } else if (F==' U' )
288+ undefs.insert (fval);
289+ else if (F==' I' ) {
290+ std::string i = fval;
291+ if (i.size () > 1 && i[0 ] == ' \" ' && i.back () == ' \" ' )
292+ i = unescape (i.substr (1 , i.size () - 2 ));
293+ if (std::find (includePaths.begin (), includePaths.end (), i) == includePaths.end ())
294+ includePaths.push_back (i);
295+ } else if (F==' s' && fval.compare (0 ,2 ," td" ) == 0 ) {
296+ ++pos;
297+ const std::string stdval = readUntil (command, &pos, " " );
298+ standard = stdval;
299+ if (standard.compare (0 , 3 , " c++" ) || standard.compare (0 , 5 , " gnu++" )) {
300+ std::string stddef;
301+ if (standard == " c++98" || standard == " gnu++98" || standard == " c++03" || standard == " gnu++03" ) {
302+ stddef = " 199711L" ;
303+ } else if (standard == " c++11" || standard == " gnu++11" || standard == " c++0x" || standard == " gnu++0x" ) {
304+ stddef = " 201103L" ;
305+ } else if (standard == " c++14" || standard == " gnu++14" || standard == " c++1y" || standard == " gnu++1y" ) {
306+ stddef = " 201402L" ;
307+ } else if (standard == " c++17" || standard == " gnu++17" || standard == " c++1z" || standard == " gnu++1z" ) {
308+ stddef = " 201703L" ;
309+ }
310+
311+ if (stddef.empty ()) {
312+ // TODO: log error
313+ continue ;
314+ }
334315
335- if (opt==" D" )
336- parseCommandDefine (command, &pos, defs);
337- else if (opt==" U" )
338- parseCommandUndefine (command, &pos);
339- else if (opt==" I" )
340- parseCommandInclude (command, &pos);
341- else if (opt==" isystem" )
342- parseCommandSystemInclude (command, &pos);
343- else if (opt==" std" )
344- parseCommandStd (command, &pos, defs);
345- else if (opt==" municode" )
346- defs += " UNICODE;" ;
347- else if (opt==" fpic" )
348- defs += " __pic__;" ;
349- else if (opt==" fPIC" )
350- defs += " __PIC__;" ;
351- else if (opt==" fpie" )
352- defs += " __pie__;" ;
353- else if (opt==" fPIE" )
354- defs += " __PIE__;" ;
316+ defs += " __cplusplus=" ;
317+ defs += stddef;
318+ defs += " ;" ;
319+ } else if (standard.compare (0 , 1 , " c" ) || standard.compare (0 , 3 , " gnu" )) {
320+ if (standard == " c90" || standard == " iso9899:1990" || standard == " gnu90" || standard == " iso9899:199409" ) {
321+ // __STDC_VERSION__ is not set for C90 although the macro was added in the 1994 amendments
322+ continue ;
323+ }
324+
325+ std::string stddef;
326+
327+ if (standard == " c99" || standard == " iso9899:1999" || standard == " gnu99" ) {
328+ stddef = " 199901L" ;
329+ } else if (standard == " c11" || standard == " iso9899:2011" || standard == " gnu11" || standard == " c1x" || standard == " gnu1x" ) {
330+ stddef = " 201112L" ;
331+ } else if (standard == " c17" ) {
332+ stddef = " 201710L" ;
333+ }
334+
335+ if (stddef.empty ()) {
336+ // TODO: log error
337+ continue ;
338+ }
339+
340+ defs += " __STDC_VERSION__=" ;
341+ defs += stddef;
342+ defs += " ;" ;
343+ }
344+ } else if (F == ' i' && fval == " system" ) {
345+ ++pos;
346+ const std::string isystem = readUntil (command, &pos, " " );
347+ systemIncludePaths.push_back (isystem);
348+ } else if (F==' m' ) {
349+ if (fval == " unicode" ) {
350+ defs += " UNICODE" ;
351+ defs += " ;" ;
352+ }
353+ } else if (F==' f' ) {
354+ if (fval == " pic" ) {
355+ defs += " __pic__" ;
356+ defs += " ;" ;
357+ } else if (fval == " PIC" ) {
358+ defs += " __PIC__" ;
359+ defs += " ;" ;
360+ } else if (fval == " pie" ) {
361+ defs += " __pie__" ;
362+ defs += " ;" ;
363+ } else if (fval == " PIE" ) {
364+ defs += " __PIE__" ;
365+ defs += " ;" ;
366+ }
367+ }
355368 }
356369 setDefines (defs);
357370}
0 commit comments