diff --git a/engine/class_modules/apl/ConvertAPL.py b/engine/class_modules/apl/ConvertAPL.py index f25f63facfb..3a414c7317f 100644 --- a/engine/class_modules/apl/ConvertAPL.py +++ b/engine/class_modules/apl/ConvertAPL.py @@ -28,6 +28,18 @@ '# Executed every time the actor is available.', ] +def strip_whitespace_preserve_quotes(s): + """Strip whitespace outside of double-quoted regions.""" + result = [] + in_quotes = False + for c in s: + if c == '"': + in_quotes = not in_quotes + result.append(c) + elif in_quotes or not c.isspace(): + result.append(c) + return ''.join(result) + # Returns the next SimC string/line in file (defined as a comment line or TCI syntax to next whitespace) def read_by_whitespace(fileObj): for line in fileObj: @@ -35,8 +47,9 @@ def read_by_whitespace(fileObj): if line.strip() not in ignored_comments: yield line else: - for token in line.split(): # If it doesn't then just yield until next whitespace as TCI commands count them as line breaks - yield token + stripped = strip_whitespace_preserve_quotes(line) + if stripped: + yield stripped # Opens the input file and generates C++ syntax apl from the given TCI syntax APL. List of sub-action lists returned in subaplList and list of actions (with comments) returned in aplList. aplList is formatted already. def read_apl(inputFilePath): diff --git a/engine/sim/option.cpp b/engine/sim/option.cpp index 911c5688856..0da1f05aae4 100644 --- a/engine/sim/option.cpp +++ b/engine/sim/option.cpp @@ -722,13 +722,32 @@ void option_db_t::parse_line( util::string_view line ) return; } - auto tokens = util::string_split_allow_quotes( line, " \t\n\r" ); + // Strip whitespace outside of double-quoted regions. + // Since spaces are never valid within option tokens (they are + // already used as token separators), this is a lossless operation + // that allows users to write readable .simc files with spaces. + std::string stripped; + stripped.reserve( line.size() ); + bool in_quotes = false; + for ( char c : line ) + { + if ( c == '"' ) + { + in_quotes = !in_quotes; + stripped += c; + } + else if ( in_quotes || !is_white_space( c ) ) + { + stripped += c; + } + } + + auto tokens = util::string_split_allow_quotes( stripped, " \t\n\r" ); - for( const auto& token : tokens ) + for ( const auto& token : tokens ) { parse_token( token ); } - } // option_db_t::parse_token =================================================