Index: include/lldb/Interpreter/OptionValue.h =================================================================== --- include/lldb/Interpreter/OptionValue.h +++ include/lldb/Interpreter/OptionValue.h @@ -58,9 +58,11 @@ eDumpOptionValue = (1u << 2), eDumpOptionDescription = (1u << 3), eDumpOptionRaw = (1u << 4), + eDumpOptionCommand = (1u << 5), eDumpGroupValue = (eDumpOptionName | eDumpOptionType | eDumpOptionValue), eDumpGroupHelp = - (eDumpOptionName | eDumpOptionType | eDumpOptionDescription) + (eDumpOptionName | eDumpOptionType | eDumpOptionDescription), + eDumpGroupExport = (eDumpOptionCommand | eDumpOptionName | eDumpOptionValue) }; OptionValue() Index: lit/Settings/TestExport.test =================================================================== --- /dev/null +++ lit/Settings/TestExport.test @@ -0,0 +1,7 @@ +# This tests exporting settings from LLDB. It checks that the settings can be +# written to file and read again without altering any of the values. + +# RUN: %lldb -b -o 'settings export %t.foo' -o 'command source %t.foo' -o 'settings export %t.bar' -o 'command source %t.bar' 2>&1 | FileCheck %s +# RUN: diff -w %t.foo %t.bar + +# CHECK-NOT: error: Index: source/Commands/CommandObjectSettings.cpp =================================================================== --- source/Commands/CommandObjectSettings.cpp +++ source/Commands/CommandObjectSettings.cpp @@ -185,7 +185,7 @@ return false; const size_t argc = cmd_args.GetArgumentCount(); - if ((argc < 2) && (!m_options.m_global)) { + if ((argc < 1) && (!m_options.m_global)) { result.AppendError("'settings set' takes more arguments"); result.SetStatus(eReturnStatusFailed); return false; @@ -199,6 +199,18 @@ return false; } + // A missing value corresponds to clearing the setting. + if (argc == 1) { + Status error(m_interpreter.GetDebugger().SetPropertyValue( + &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef())); + if (error.Fail()) { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + return result.Succeeded(); + } + // Split the raw command into var_name and value pair. llvm::StringRef raw_str(command); std::string var_value_string = raw_str.split(var_name).second.str(); @@ -300,6 +312,63 @@ } }; +//------------------------------------------------------------------------- +// CommandObjectSettingsExport -- Export current values +//------------------------------------------------------------------------- + +class CommandObjectSettingsExport : public CommandObjectParsed { +public: + CommandObjectSettingsExport(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "settings export", + "Export debugger settings and their current values.", nullptr) { + CommandArgumentEntry arg1; + CommandArgumentData var_name_arg; + + // Define the first (and only) variant of this arg. + var_name_arg.arg_type = eArgTypeFilename; + var_name_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the + // argument entry. + arg1.push_back(var_name_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back(arg1); + } + + ~CommandObjectSettingsExport() override = default; + + int HandleArgumentCompletion( + CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion, + request, nullptr); + return request.GetNumberOfMatches(); + } + +protected: + bool DoExecute(Args &args, CommandReturnObject &result) override { + result.SetStatus(eReturnStatusSuccessFinishResult); + + // Open file for dumping the exported settings. + const std::string export_path = args.GetArgumentAtIndex(0); + const uint32_t options = File::eOpenOptionWrite | + File::eOpenOptionTruncate | + File::eOpenOptionCanCreate; + StreamFile export_file(export_path.c_str(), options); + + // Exporting should not be context sensitive. + ExecutionContext clean_ctx; + + m_interpreter.GetDebugger().DumpAllPropertyValues( + &clean_ctx, export_file, OptionValue::eDumpGroupExport); + + return result.Succeeded(); + } +}; + //------------------------------------------------------------------------- // CommandObjectSettingsList -- List settable variables //------------------------------------------------------------------------- @@ -987,6 +1056,8 @@ CommandObjectSP(new CommandObjectSettingsAppend(interpreter))); LoadSubCommand("clear", CommandObjectSP(new CommandObjectSettingsClear(interpreter))); + LoadSubCommand("export", + CommandObjectSP(new CommandObjectSettingsExport(interpreter))); } CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default; Index: source/Interpreter/OptionValueArray.cpp =================================================================== --- source/Interpreter/OptionValueArray.cpp +++ source/Interpreter/OptionValueArray.cpp @@ -31,13 +31,17 @@ strm.Printf("(%s)", GetTypeAsCString()); } if (dump_mask & eDumpOptionValue) { - if (dump_mask & eDumpOptionType) - strm.Printf(" =%s", (m_values.size() > 0) ? "\n" : ""); - strm.IndentMore(); + const bool one_line = dump_mask & eDumpOptionCommand; const uint32_t size = m_values.size(); + if (dump_mask & eDumpOptionType) + strm.Printf(" =%s", (m_values.size() > 0 && !one_line) ? "\n" : ""); + if (!one_line) + strm.IndentMore(); for (uint32_t i = 0; i < size; ++i) { - strm.Indent(); - strm.Printf("[%u]: ", i); + if (!one_line) { + strm.Indent(); + strm.Printf("[%u]: ", i); + } const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; switch (array_element_type) { default: @@ -63,10 +67,16 @@ extra_dump_options); break; } - if (i < (size - 1)) - strm.EOL(); + + if (!one_line) { + if (i < (size - 1)) + strm.EOL(); + } else { + strm << ' '; + } } - strm.IndentLess(); + if (!one_line) + strm.IndentLess(); } } Index: source/Interpreter/OptionValueDictionary.cpp =================================================================== --- source/Interpreter/OptionValueDictionary.cpp +++ source/Interpreter/OptionValueDictionary.cpp @@ -33,16 +33,23 @@ strm.Printf("(%s)", GetTypeAsCString()); } if (dump_mask & eDumpOptionValue) { + const bool one_line = dump_mask & eDumpOptionCommand; if (dump_mask & eDumpOptionType) strm.PutCString(" ="); collection::iterator pos, end = m_values.end(); - strm.IndentMore(); + if (!one_line) + strm.IndentMore(); for (pos = m_values.begin(); pos != end; ++pos) { OptionValue *option_value = pos->second.get(); - strm.EOL(); + + if (one_line) + strm << ' '; + else + strm.EOL(); + strm.Indent(pos->first.GetCString()); const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; @@ -74,7 +81,8 @@ break; } } - strm.IndentLess(); + if (!one_line) + strm.IndentLess(); } } Index: source/Interpreter/OptionValueFileSpecLIst.cpp =================================================================== --- source/Interpreter/OptionValueFileSpecLIst.cpp +++ source/Interpreter/OptionValueFileSpecLIst.cpp @@ -25,16 +25,24 @@ if (dump_mask & eDumpOptionType) strm.Printf("(%s)", GetTypeAsCString()); if (dump_mask & eDumpOptionValue) { - if (dump_mask & eDumpOptionType) - strm.Printf(" =%s", m_current_value.GetSize() > 0 ? "\n" : ""); - strm.IndentMore(); + const bool one_line = dump_mask & eDumpOptionCommand; const uint32_t size = m_current_value.GetSize(); + if (dump_mask & eDumpOptionType) + strm.Printf(" =%s", + (m_current_value.GetSize() > 0 && !one_line) ? "\n" : ""); + if (!one_line) + strm.IndentMore(); for (uint32_t i = 0; i < size; ++i) { - strm.Indent(); - strm.Printf("[%u]: ", i); + if (!one_line) { + strm.Indent(); + strm.Printf("[%u]: ", i); + } m_current_value.GetFileSpecAtIndex(i).Dump(&strm); + if (one_line) + strm << ' '; } - strm.IndentLess(); + if (!one_line) + strm.IndentLess(); } } Index: source/Interpreter/OptionValueFormatEntity.cpp =================================================================== --- source/Interpreter/OptionValueFormatEntity.cpp +++ source/Interpreter/OptionValueFormatEntity.cpp @@ -61,10 +61,10 @@ strm.Printf("(%s)", GetTypeAsCString()); if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) - strm.PutCString(" = \""); + strm.PutCString(" = "); std::string escaped; EscapeBackticks(m_current_format, escaped); - strm << escaped << '"'; + strm << '"' << escaped << '"'; } } Index: source/Interpreter/OptionValueLanguage.cpp =================================================================== --- source/Interpreter/OptionValueLanguage.cpp +++ source/Interpreter/OptionValueLanguage.cpp @@ -28,7 +28,8 @@ if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) strm.PutCString(" = "); - strm.PutCString(Language::GetNameForLanguageType(m_current_value)); + if (m_current_value != eLanguageTypeUnknown) + strm.PutCString(Language::GetNameForLanguageType(m_current_value)); } } Index: source/Interpreter/Property.cpp =================================================================== --- source/Interpreter/Property.cpp +++ source/Interpreter/Property.cpp @@ -233,7 +233,10 @@ uint32_t dump_mask) const { if (m_value_sp) { const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription; + const bool dump_cmd = dump_mask & OptionValue::eDumpOptionCommand; const bool transparent = m_value_sp->ValueIsTransparent(); + if (dump_cmd && !transparent) + strm << "settings set "; if (dump_desc || !transparent) { if ((dump_mask & OptionValue::eDumpOptionName) && m_name) { DumpQualifiedName(strm);