[nemiver] Move core asm handling lower in the stack.
- From: Dodji Seketeli <dodji src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver] Move core asm handling lower in the stack.
- Date: Mon, 6 Sep 2010 19:52:31 +0000 (UTC)
commit 19a94bbf0bac34009337bc4287a2efbc49d3929c
Author: Dodji Seketeli <dodji redhat com>
Date: Sun Aug 29 00:09:17 2010 +0200
Move core asm handling lower in the stack.
* src/dbgengine/nmv-asm-utils.h: Move content from here to ...
* common/nmv-asm-utils.h: ... here.
* common/nmv-asm-utils.cc: New file.
* src/common/Makefile.am: Add nmv-asm-utils.[h|cc] to the build
system.
* src/dbgengine/Makefile.am: Remove nmv-asm-utils.[h|cc] from the
build system.
* src/dbgengine/nmv-gdbmi-parser.cc: Don't include nmv-asm-utils.h
anymore.
* tests/test-disassemble.cc: Include common/nmv-asm-utils.h
instead of just nmv-asm-utils.h.
* tests/test-gdbmi.cc: Likewise.
* src/common/nmv-env.h (find_file, find_file_absolute_or_relative)
(read_file_line): Declare ...
* src/common/nmv-env.cc (find_file, find_file_absolute_or_relative)
(read_file_line): ... new functions.
* src/common/nmv-str-utils.h (is_buffer_valid_utf8)
(ensure_buffer_is_in_utf8): Declare ...
* src/common/nmv-str-utils.cc (is_buffer_valid_utf8)
(ensure_buffer_is_in_utf8): ... new functions.
* src/common/nmv-ustring.h (UString::split_to_list): Declare new function.
* src/common/nmv-ustring.cc (split_base): New function template.
(UString::split): Use the new splite_base function template.
(UString::split_to_list): Define new function. Uses splite_base.
* src/uicommon/nmv-dialog.[h|cc]: Moved here from
src/persp/dbgperspective/nmv-dialog.[h|cc].
(Dialog::Priv::Priv): Support loading glade file from the "global"
glade install dir of Nemiver as well as from the plugins glade
install dir.
* glade/locatefiledialog.glade: Moved here from
src/persp/dbgperspective/glade/locatefiledialog.glade.
* glade/Makefile.am: Add locatefiledialog.glade file to build system.
* src/uicommon/nmv-locate-file-dialog.[h|cc]: Moved here from
src/persp/dbgperspective/nmv-locate-file-dialog.[h|cc].
* src/uicommon/Makefile.am: Add nmv-dialog.[h|cc] and
nmv-locate-file-dialog.cc to the build system.
* src/uicommon/nmv-ui-utils.cc|h (ask_user_to_select_file)
(find_absolute_path_or_ask_user, find_file_and_read_line): New
functions. Moved here from DBGPerspective and hacked to fit in here.
* src/uicommon/nmv-source-editor.cc|h
(SourceEditor::get_file_mime_type)
(SourceEditor::setup_buffer_mime_and_lang)
(SourceEditor::create_source_buffer)
(SourceEditor::load_file, SourceEditor::add_asm)
(SourceEditor::load_asm): New functions. Mostly the result of
moving their counterparts from DBGPerspective to here. They got
also hacked to use new support functions from the common::env and
ui_utils namespace.
* src/persp/dbgperspective/glade/locatefiledialog.glade: Moved to
glade/locatefiledialog.glade.
* src/persp/dbgperspective/glade/Makefile.am: Remove
locatefiledialog.glade from the build system here.
* src/persp/dbgperspective/Makefile.am: Remove nmv-dialog.[cc|h] and
nmv-locate-file-dialog.[h|cc] from the build system here.
* src/persp/dbgperspective/nmv-dbg-perspective.h (load_asm): Remove.
* src/persp/dbgperspective/nmv-dbg-perspective.cc (log_asm_insns)
(get_file_mime_type, setup_buffer_mime_and_lang)
(create_source_buffer, load_file, load_asm, write_asm_instr)
(write_asm_instr, add_asm, read_file_line): Remove these
functions. Actually they got moved to lower level layers in the
stack, i.e, mostly into nmv-source-editor.cc, nmv-ui-utils.cc, and
nmv-env.cc.
(get_global_search_paths): get_source_dirs got renamed into this.
(DBGPerspective::Priv::session_search_paths): Renamed
DBGPerspective::Priv::search_paths into this.
(DBGPerspective::Priv::global_search_paths): Renamed
DBGPerspective::Priv::source_dirs into this.
(Priv::get_supported_encodings): New function.
(Priv::load_file): New function. Use get_supported_encodings and
the new SourceEditor::load_file.
(find_absolute_path): Use the new
common::env::find_file_absolute_or_relative.
(find_absolute_path_or_ask_user): Use the new
ui_utils::find_absolute_path_or_ask_user.
(get_or_append_asm_source_editor): Use the new
SourceEditor::create_source_buffer.
(find_file_in_source_dirs): Use the new common::env::find_file.
(open_file_real): Use the Priv::load_file, instead of the new
defunct load_file.
(open_asm): Use the new SourceEditor::load_asm instead of the
defunct load_asm.
(switch_to_asm): use the new
SourceEditor::setup_buffer_mime_and_lang and SourceEditor::load_asm.
(switch_to_source_code): Use the new
SourceEditor::get_file_mime_type,
SourceEditor::setup_buffer_mime_and_lang and Priv::load_file.
(reload_file): Use the Priv::load_file.
(ask_user_to_select_file): Use the new
ui_utils::ask_user_to_select_file.
glade/Makefile.am | 2 +-
.../glade => glade}/locatefiledialog.glade | 0
src/common/Makefile.am | 2 +
src/common/nmv-asm-instr.h | 6 +-
src/common/nmv-asm-utils.h | 147 ++++
src/common/nmv-env.cc | 155 ++++
src/common/nmv-env.h | 20 +
src/common/nmv-str-utils.cc | 91 +++
src/common/nmv-str-utils.h | 7 +
src/common/nmv-ustring.cc | 25 +-
src/common/nmv-ustring.h | 1 +
src/dbgengine/Makefile.am | 2 +-
src/dbgengine/nmv-asm-utils.h | 91 ---
src/dbgengine/nmv-gdbmi-parser.cc | 1 -
src/dbgengine/nmv-i-debugger.h | 4 +-
src/persp/dbgperspective/Makefile.am | 4 -
src/persp/dbgperspective/glade/Makefile.am | 1 -
src/persp/dbgperspective/nmv-dbg-perspective.cc | 777 ++------------------
src/persp/dbgperspective/nmv-dbg-perspective.h | 4 -
src/uicommon/Makefile.am | 4 +
.../dbgperspective => uicommon}/nmv-dialog.cc | 21 +-
.../dbgperspective => uicommon}/nmv-dialog.h | 0
.../nmv-locate-file-dialog.cc | 0
.../nmv-locate-file-dialog.h | 0
src/uicommon/nmv-source-editor.cc | 312 ++++++++-
src/uicommon/nmv-source-editor.h | 38 +
src/uicommon/nmv-ui-utils.cc | 113 +++-
src/uicommon/nmv-ui-utils.h | 23 +
tests/test-disassemble.cc | 2 +-
tests/test-gdbmi.cc | 2 +-
30 files changed, 1032 insertions(+), 823 deletions(-)
---
diff --git a/glade/Makefile.am b/glade/Makefile.am
index 58d91ef..9c9bd35 100644
--- a/glade/Makefile.am
+++ b/glade/Makefile.am
@@ -1,4 +1,4 @@
-gladefiles = workbench.glade
+gladefiles = workbench.glade locatefiledialog.glade
gladedir = $(datadir)/@PACKAGE@/glade
glade_DATA = $(gladefiles)
diff --git a/src/persp/dbgperspective/glade/locatefiledialog.glade b/glade/locatefiledialog.glade
similarity index 100%
rename from src/persp/dbgperspective/glade/locatefiledialog.glade
rename to glade/locatefiledialog.glade
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 525d97e..a238df5 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -7,6 +7,7 @@ nmv-namespace.h \
nmv-ustring.h \
nmv-address.h \
nmv-asm-instr.h \
+nmv-asm-utils.h \
nmv-range.h \
nmv-str-utils.h \
nmv-libxml-utils.h \
@@ -43,6 +44,7 @@ nmv-proc-mgr.h
libnemivercommon_la_SOURCES= $(headers) \
nmv-ustring.cc \
nmv-address.cc \
+nmv-asm-utils.cc \
nmv-str-utils.cc \
nmv-object.cc \
nmv-libxml-utils.cc \
diff --git a/src/common/nmv-asm-instr.h b/src/common/nmv-asm-instr.h
index 356ae88..1cdd71f 100644
--- a/src/common/nmv-asm-instr.h
+++ b/src/common/nmv-asm-instr.h
@@ -24,10 +24,12 @@
*/
#ifndef __NEMIVER_ASM_INSTR_H__
#define __NEMIVER_ASM_INSTR_H__
+
+#include <list>
+#include <boost/variant.hpp>
#include "nmv-namespace.h"
#include "nmv-api-macros.h"
-#include <boost/variant.hpp>
-#include <list>
+#include "nmv-exception.h"
NEMIVER_BEGIN_NAMESPACE (nemiver)
NEMIVER_BEGIN_NAMESPACE (common)
diff --git a/src/common/nmv-asm-utils.h b/src/common/nmv-asm-utils.h
new file mode 100644
index 0000000..08454a5
--- /dev/null
+++ b/src/common/nmv-asm-utils.h
@@ -0,0 +1,147 @@
+// Author: Dodji Seketeli
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NEMIVER_ASM_UTILS_H__
+#define __NEMIVER_ASM_UTILS_H__
+
+#include "nmv-asm-instr.h"
+
+using nemiver::common::UString;
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+NEMIVER_BEGIN_NAMESPACE (common)
+
+template<class Stream>
+Stream&
+operator<< (Stream &a_out, const AsmInstr &a_instr)
+{
+ a_out << "<asm-instr>\n"
+ << " <addr>" << a_instr.address () << "</addr>\n"
+ << " <function-name>" << a_instr.function () << "</function-name>\n"
+ << " <offset>" << a_instr.offset () << "</offset>\n"
+ << " <instr>" << a_instr.instruction () << "</instr>\n"
+ << "</asm-instr>\n";
+ return a_out;
+}
+
+template<class Stream>
+Stream&
+operator<< (Stream &a_out, const MixedAsmInstr &a_instr)
+{
+ a_out << "<asm-mixed-instr>\n"
+ << " <line>" << a_instr.line_number () << "</line>\n"
+ << " <path>" << a_instr.file_path () << "</path>\n";
+
+ list<AsmInstr>::const_iterator it;
+ a_out << " <asm-instr-list>";
+ for (it = a_instr.instrs ().begin ();
+ it != a_instr.instrs ().end ();
+ ++it) {
+ a_out << " <asm-instr>\n"
+ << " <addr>" << it->address () << "</addr>\n"
+ << " <function-name>" << it->function ()
+ << "</function-name>\n"
+ << " <offset>" << it->offset () << "</offset>\n"
+ << " <instr>" << it->instruction () << "</instr>\n"
+ << " </asm-instr>\n";
+ }
+ a_out << " </asm-instr-list>"
+ << "</asm-mixed-instr>\n";
+
+ return a_out;
+}
+
+template<class Stream>
+Stream&
+operator<< (Stream &a_out, const Asm &a_asm)
+{
+ switch (a_asm.which ()) {
+ case Asm::TYPE_PURE:
+ a_out << a_asm.instr ();
+ break;
+ case Asm::TYPE_MIXED:
+ a_out << a_asm.mixed_instr ();
+ break;
+ default:
+ THROW ("reached unreachable");
+ }
+ return a_out;
+}
+
+void log_asm_insns (const std::list<common::Asm> &a_asm);
+
+typedef bool (* FindFileAndReadLine) (const UString &a_file_path,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_sess_dirs,
+ const list<UString> &a_glob_dirs,
+ map<UString, bool> &a_ignore_paths,
+ bool a_ignore_if_not_found,
+ int a_line_number,
+ std::string &a_line);
+class ReadLine
+{
+ private:
+ ReadLine ();
+ ReadLine (const ReadLine &);
+
+ protected:
+ const UString &m_prog_path;
+ const UString &m_cwd;
+ list<UString> &m_session_dirs;
+ const list<UString> &m_global_dirs;
+ map<UString, bool> &m_ignore_paths;
+ FindFileAndReadLine read_line;
+
+ public:
+ ReadLine (const UString &prog_path,
+ const UString &cwd,
+ list<UString> &session_dirs,
+ const list<UString> &global_dirs,
+ map<UString, bool> &ignore_paths,
+ FindFileAndReadLine read_line_func) :
+ m_prog_path (prog_path), m_cwd (cwd), m_session_dirs (session_dirs),
+ m_global_dirs (global_dirs), m_ignore_paths (ignore_paths),
+ read_line (read_line_func)
+ {
+ }
+
+ bool operator () (const UString &a_file_path,
+ int a_line_number,
+ std::string &a_line)
+ {
+ return read_line (a_file_path, m_prog_path, m_cwd, m_session_dirs,
+ m_global_dirs, m_ignore_paths, true, a_line_number,
+ a_line);
+ }
+};
+
+bool write_asm_instr (const common::Asm &a_asm,
+ ReadLine &a_read,
+ std::ostringstream &a_os);
+
+NEMIVER_END_NAMESPACE (common)
+NEMIVER_END_NAMESPACE (nemiver)
+
+#endif // __NEMIVER_ASM_UTILS_H__
diff --git a/src/common/nmv-env.cc b/src/common/nmv-env.cc
index eb7aa52..53cc2b9 100644
--- a/src/common/nmv-env.cc
+++ b/src/common/nmv-env.cc
@@ -32,6 +32,7 @@
#include <fcntl.h>
#include <string>
#include <vector>
+#include <fstream>
#include <glibmm.h>
#include "nmv-env.h"
#include "nmv-ustring.h"
@@ -376,6 +377,160 @@ build_path_to_executable (const UString &a_exe_name,
return true;
}
+bool
+find_file (const UString &a_file_name,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ const list<UString> &a_session_dirs,
+ const list<UString> &a_global_dirs,
+ UString &a_file_path)
+{
+ string file_name = Glib::filename_from_utf8 (a_file_name),
+ path,
+ candidate;
+
+ // first check if this is an absolute path
+ if (Glib::path_is_absolute (file_name)) {
+ if (Glib::file_test (file_name, Glib::FILE_TEST_IS_REGULAR)) {
+ a_file_path = Glib::filename_to_utf8 (file_name);
+ return true;
+ }
+ }
+ // then look in the working directory
+ candidate = Glib::build_filename (a_cwd, file_name);
+ if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
+ a_file_path = Glib::filename_to_utf8 (candidate);
+ return true;
+ }
+ // then look in the directory of the binary
+ candidate =
+ Glib::build_filename (Glib::path_get_dirname (a_prog_path),
+ file_name);
+ if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
+ a_file_path = Glib::filename_to_utf8 (candidate);
+ return true;
+ }
+ // then look in the session-specific search paths
+ list<UString>::const_iterator session_iter;
+ for (session_iter = a_session_dirs.begin ();
+ session_iter != a_session_dirs.end ();
+ ++session_iter) {
+ path = Glib::filename_from_utf8 (*session_iter);
+ candidate = Glib::build_filename (path, file_name);
+ if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
+ a_file_path = Glib::filename_to_utf8 (candidate);
+ return true;
+ }
+ }
+ // if not found, then look in the global search paths
+ list<UString>::const_iterator global_iter;
+ for (global_iter = a_global_dirs.begin ();
+ global_iter != a_global_dirs.end ();
+ ++global_iter) {
+ path = Glib::filename_from_utf8 (*global_iter);
+ candidate = Glib::build_filename (path, file_name);
+ if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
+ a_file_path = Glib::filename_to_utf8 (candidate);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+find_file_absolute_or_relative (const UString &a_file_name,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ const list<UString> &a_session_dirs,
+ const list<UString> &a_global_dirs,
+ UString &a_file_path)
+{
+ // First, assume it's a full path name already.
+ if (Glib::file_test (a_file_name, Glib::FILE_TEST_IS_REGULAR)) {
+ a_file_path = a_file_name;
+ return true;
+ }
+
+ // If that didn't work, look for a file of that name in the search
+ // directories.
+ if (find_file (a_file_name, a_prog_path, a_cwd,
+ a_session_dirs, a_global_dirs,
+ a_file_path)) {
+ return true;
+ }
+
+ // Then look for a file of that basename in the search directories.
+ std::string basename =
+ Glib::path_get_basename (Glib::filename_from_utf8 (a_file_name));
+ if (basename != a_file_name
+ && find_file (basename, a_prog_path, a_cwd,
+ a_session_dirs, a_global_dirs,
+ a_file_path)) {
+ return true;
+ }
+ return false;
+}
+
+/// Given a file path P and a line number N , reads the line N from P
+/// and return it iff the function returns true. This is useful
+/// e.g. when forging a mixed source/assembly source view, and we want
+/// to display a source line N from a file P.
+///
+/// \param a_file_path the absolute file path to consider
+/// \param a_line_number the line number to consider
+/// \param a_line the string containing the resulting line read, if
+/// and only if the function returned true.
+/// \return true upon successful completion, false otherwise.
+bool
+read_file_line (const UString &a_file_path,
+ int a_line_number,
+ string &a_line)
+{
+ if (a_file_path.empty ())
+ return false;
+
+ bool found_line = false;
+ int line_num = 1;
+ char c = 0;
+
+ NEMIVER_TRY;
+
+ std::ifstream file (a_file_path.c_str ());
+
+ if (!file.good ()) {
+ LOG_ERROR ("Could not open file " + a_file_path);
+ return false;
+ }
+
+ while (true) {
+ if (line_num == a_line_number) {
+ found_line = true;
+ break;
+ }
+ file.get (c);
+ if (!file.good ())
+ break;
+ if (c == '\n')
+ ++line_num;
+ }
+ if (found_line) {
+ a_line.clear ();
+ while (true) {
+ file.get (c);
+ if (!file.good ())
+ break;
+ if (c == '\n')
+ break;
+ a_line += c;
+ }
+ }
+ file.close ();
+
+ NEMIVER_CATCH_NOX;
+
+ return found_line;
+}
+
NEMIVER_END_NAMESPACE (env)
NEMIVER_END_NAMESPACE (common)
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/common/nmv-env.h b/src/common/nmv-env.h
index 32e79cd..7181433 100644
--- a/src/common/nmv-env.h
+++ b/src/common/nmv-env.h
@@ -34,6 +34,8 @@
#include "nmv-ustring.h"
#include "nmv-exception.h"
+using nemiver::common::UString;
+
NEMIVER_BEGIN_NAMESPACE (nemiver)
NEMIVER_BEGIN_NAMESPACE (common)
NEMIVER_BEGIN_NAMESPACE (env)
@@ -81,6 +83,24 @@ NEMIVER_API UString build_path_to_help_file (const UString &a_file_name);
NEMIVER_API bool build_path_to_executable (const UString &a_exe_name,
UString &a_exe_path);
+NEMIVER_API bool find_file (const UString &a_file_name,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ const list<UString> &a_session_dirs,
+ const list<UString> &a_global_dirs,
+ UString &a_file_path);
+
+NEMIVER_API bool find_file_absolute_or_relative (const UString &a_file_name,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ const list<UString> &a_sess_dirs,
+ const list<UString> &a_glob_dirs,
+ UString &a_file_path);
+
+NEMIVER_API bool read_file_line (const UString &a_file_path,
+ int a_line_number,
+ string &a_line);
+
NEMIVER_END_NAMESPACE (env)
NEMIVER_END_NAMESPACE (common)
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/common/nmv-str-utils.cc b/src/common/nmv-str-utils.cc
index 97c0f58..daffc6b 100644
--- a/src/common/nmv-str-utils.cc
+++ b/src/common/nmv-str-utils.cc
@@ -26,6 +26,7 @@
#include <cstring>
#include "nmv-str-utils.h"
#include "nmv-safe-ptr-utils.h"
+#include "nmv-exception.h"
NEMIVER_BEGIN_NAMESPACE (nemiver)
NEMIVER_BEGIN_NAMESPACE (str_utils)
@@ -33,6 +34,17 @@ NEMIVER_BEGIN_NAMESPACE (str_utils)
using nemiver::common::UString;
using namespace nemiver::common;
+static const char *SUPPORTED_ENCODINGS[] =
+{
+ "UTF-8",
+ "ISO-8859",
+ "ISO-8859-1",
+ "ISO-8859-15",
+};
+
+#define SIZE_OF_SUPPORTED_ENCODINGS \
+sizeof (SUPPORTED_ENCODINGS)/sizeof (SUPPORTED_ENCODINGS[0])
+
// Return true if a_str is a location string of the form
// "filename:number", where number is string of digits.
// Keep in mind that filename can also be a path that contains ':'
@@ -292,5 +304,84 @@ vprintf (const UString &a_format, va_list a_args)
return result;
}
+bool
+is_buffer_valid_utf8 (const char *a_buffer, unsigned a_len)
+{
+
+ RETURN_VAL_IF_FAIL (a_buffer, false);
+ const char *end=0;
+ bool is_valid = g_utf8_validate (a_buffer, a_len, &end);
+ return is_valid;
+}
+
+bool
+ensure_buffer_is_in_utf8 (const std::string &a_input,
+ const std::list<std::string> &a_supported_encodings,
+ UString &a_output)
+{
+ UString buf_content;
+ if (is_buffer_valid_utf8 (a_input.c_str (), a_input.size ())) {
+ a_output = a_input;
+ return true;
+ }
+
+ UString utf8_content;
+ bool converted = false;
+
+ // get the list of candidate encodings that could be the encoding
+ // of the a_input. If for a reason we cannot sucessfully proceed
+ // with the conversion then we will fall back to a hardcoded list
+ // of encodings.
+ std::string current_charset;
+ if (!a_supported_encodings.empty ()) {
+ std::list<std::string>::const_iterator it;
+ for (it = a_supported_encodings.begin ();
+ it != a_supported_encodings.end ();
+ ++it) {
+ current_charset = *it;
+ try {
+ utf8_content =
+ Glib::convert (a_input, "UTF-8", current_charset);
+ } catch (Glib::Exception &e) {
+ continue;
+ } catch (...) {
+ return false;
+ }
+ converted = true;
+ break;
+ }
+ }
+
+ if (!converted) {
+ // fall back to trying the hardcoded list of supported encodings
+ for (unsigned int i=0; i < SIZE_OF_SUPPORTED_ENCODINGS; i++) {
+ try {
+ utf8_content =
+ Glib::convert (a_input,
+ "UTF-8",
+ SUPPORTED_ENCODINGS[i]);
+ } catch (Glib::Exception &e) {
+ continue;
+ } catch (...) {
+ return false;
+ }
+ converted = true;
+ }
+ }
+
+ if (!converted)
+ return false;
+
+ const char *end=0;
+ if (utf8_content.empty ()
+ || !g_utf8_validate (utf8_content.raw ().c_str (),
+ utf8_content.bytes (),
+ &end)) {
+ return false;
+ }
+ a_output = utf8_content;
+ return true;
+}
+
NEMIVER_END_NAMESPACE (str_utils)
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/common/nmv-str-utils.h b/src/common/nmv-str-utils.h
index 76490cd..65b798d 100644
--- a/src/common/nmv-str-utils.h
+++ b/src/common/nmv-str-utils.h
@@ -82,6 +82,13 @@ UString printf (const UString &a_format, ...);
UString vprintf (const UString &a_format, va_list a_args);
+bool is_buffer_valid_utf8 (const char *a_buffer, unsigned a_len);
+
+bool ensure_buffer_is_in_utf8 (const std::string &a_input,
+ const std::list<std::string> &supported_encodings,
+ UString &a_output);
+
+
NEMIVER_END_NAMESPACE (str_utils)
NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/common/nmv-ustring.cc b/src/common/nmv-ustring.cc
index 8be7e7b..4e2d5d6 100644
--- a/src/common/nmv-ustring.cc
+++ b/src/common/nmv-ustring.cc
@@ -191,16 +191,17 @@ UString::operator! () const
return false;
}
-vector<UString>
-UString::split (const UString &a_delim) const
+template<class string_container>
+string_container
+split_base (const UString &a_string, const UString &a_delim)
{
- vector<UString> result;
- if (size () == Glib::ustring::size_type (0)) {return result;}
+ string_container result;
+ if (a_string.size () == Glib::ustring::size_type (0)) {return result;}
- gint len = bytes () + 1;
+ gint len = a_string.bytes () + 1;
CharSafePtr buf (new gchar[len]);
memset (buf.get (), 0, len);
- memcpy (buf.get (), c_str (), bytes ());
+ memcpy (buf.get (), a_string.c_str (), a_string.bytes ());
gchar **splited = g_strsplit (buf.get (), a_delim.c_str (), -1);
try {
@@ -217,6 +218,18 @@ UString::split (const UString &a_delim) const
}
vector<UString>
+UString::split (const UString &a_delim) const
+{
+ return split_base<vector<UString> > (*this, a_delim);
+}
+
+list<UString>
+UString::split_to_list (const UString &a_delim) const
+{
+ return split_base<list<UString> > (*this, a_delim);
+}
+
+vector<UString>
UString::split_set (const UString &a_delim_set) const
{
vector<UString> result;
diff --git a/src/common/nmv-ustring.h b/src/common/nmv-ustring.h
index 3a2acde..a181c97 100644
--- a/src/common/nmv-ustring.h
+++ b/src/common/nmv-ustring.h
@@ -64,6 +64,7 @@ public:
UString& operator= (UString const &a_cstr);
bool operator! () const;
vector<UString> split (const UString &a_delim) const;
+ list<UString> split_to_list (const UString &a_delim) const;
vector<UString> split_set (const UString &a_delim_set) const;
static UString join (const vector<UString> &a_elements,
const UString &a_delim=" ");
diff --git a/src/dbgengine/Makefile.am b/src/dbgengine/Makefile.am
index 439c441..c4e73cd 100644
--- a/src/dbgengine/Makefile.am
+++ b/src/dbgengine/Makefile.am
@@ -23,7 +23,7 @@ libdebuggerutils.la \
libgdbengine.la
idebuggerheaders= \
-nmv-i-debugger.h nmv-asm-utils.h
+nmv-i-debugger.h
ivarlistheaders= \
nmv-i-var-list.h
diff --git a/src/dbgengine/nmv-gdbmi-parser.cc b/src/dbgengine/nmv-gdbmi-parser.cc
index 7d1f6fe..29f39c6 100644
--- a/src/dbgengine/nmv-gdbmi-parser.cc
+++ b/src/dbgengine/nmv-gdbmi-parser.cc
@@ -26,7 +26,6 @@
#include <sstream>
#include "common/nmv-str-utils.h"
#include "nmv-gdbmi-parser.h"
-#include "nmv-asm-utils.h"
using nemiver::common::UString;
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index e8a7af4..101573c 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -39,8 +39,6 @@
#include "common/nmv-asm-instr.h"
#include "nmv-i-conf-mgr.h"
-NEMIVER_BEGIN_NAMESPACE (nemiver)
-
using nemiver::common::SafePtr;
using nemiver::common::DynamicModule;
using nemiver::common::DynamicModuleSafePtr;
@@ -59,6 +57,8 @@ using std::string;
using std::map;
using std::list;
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+
class ILangTrait;
class IDebugger;
typedef SafePtr<IDebugger, ObjectRef, ObjectUnref> IDebuggerSafePtr;
diff --git a/src/persp/dbgperspective/Makefile.am b/src/persp/dbgperspective/Makefile.am
index 334bef1..7bcdc56 100644
--- a/src/persp/dbgperspective/Makefile.am
+++ b/src/persp/dbgperspective/Makefile.am
@@ -24,12 +24,8 @@ pluginconfigdir= NEMIVER_PLUGINS_DIR@/$(PLUGIN_NAME)
plugin_LTLIBRARIES=libdbgperspectiveplugin.la
plugindir= NEMIVER_PLUGINS_DIR@/$(PLUGIN_NAME)
sources= \
-nmv-dialog.cc \
-nmv-dialog.h \
nmv-run-program-dialog.cc \
nmv-run-program-dialog.h \
-nmv-locate-file-dialog.cc \
-nmv-locate-file-dialog.h \
nmv-load-core-dialog.cc \
nmv-load-core-dialog.h \
nmv-saved-sessions-dialog.h \
diff --git a/src/persp/dbgperspective/glade/Makefile.am b/src/persp/dbgperspective/glade/Makefile.am
index a40be1e..a6e98b0 100644
--- a/src/persp/dbgperspective/glade/Makefile.am
+++ b/src/persp/dbgperspective/glade/Makefile.am
@@ -3,7 +3,6 @@ gladefiles = bodycontainer.glade \
runprogramdialog.glade \
proclistdialog.glade \
loadcoredialog.glade \
-locatefiledialog.glade \
savedsessionsdialog.glade \
preferencesdialog.glade \
varinspectordialog.glade \
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index c3152e3..1e27263 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -32,7 +32,6 @@
#include <unistd.h>
#include <algorithm>
#include <iostream>
-#include <fstream>
#include <sstream>
#include <glib/gi18n.h>
@@ -99,7 +98,6 @@
#include "nmv-memory-view.h"
#endif // WITH_MEMORYVIEW
#include "nmv-watchpoint-dialog.h"
-#include "nmv-asm-utils.h"
using namespace std;
using namespace nemiver::common;
@@ -131,7 +129,6 @@ const char *PROGRAM_CWD= "programcwd";
const char *LAST_RUN_TIME= "lastruntime";
const char *DBG_PERSPECTIVE_MOUSE_MOTION_DOMAIN =
"dbg-perspective-mouse-motion-domain";
-const char *DBG_PERSPECTIVE_ASM_DOMAIN = "dbg-perspective-asm-domain";
const char *DISASSEMBLY_TITLE = "<Disassembly>";
static const int NUM_INSTR_TO_DISASSEMBLE = 20;
@@ -180,21 +177,10 @@ const Gtk::StockID STOCK_STEP_INTO (STEP_INTO);
const Gtk::StockID STOCK_STEP_OVER (STEP_OVER);
const Gtk::StockID STOCK_STEP_OUT (STEP_OUT);
-const char *SUPPORTED_ENCODINGS[] =
-{
- "UTF-8",
- "ISO-8859",
- "ISO-8859-1",
- "ISO-8859-15",
-};
-
const char *I_DEBUGGER_COOKIE_EXECUTE_PROGRAM = "i-debugger-execute-program";
const char *PROG_ARG_SEPARATOR = "#DUMMY-SEP007#";
-#define SIZE_OF_SUPPORTED_ENCODINGS \
-sizeof (SUPPORTED_ENCODINGS)/sizeof (SUPPORTED_ENCODINGS[0])
-
class DBGPerspective;
#ifdef WITH_GIO
@@ -212,18 +198,6 @@ gnome_vfs_file_monitor_cb (GnomeVFSMonitorHandle *a_handle,
DBGPerspective *a_persp);
#endif
-static void
-log_asm_insns (std::list<common::Asm> a_asm)
-{
- typedef std::list<common::Asm> Asms;
- Asms::const_iterator it = a_asm.begin ();
- if (it != a_asm.end ()) {
- LOG_D (*it, DBG_PERSPECTIVE_ASM_DOMAIN);
- }
- for (++it; it != a_asm.end (); ++it) {
- LOG_D ("\n" << *it, DBG_PERSPECTIVE_ASM_DOMAIN);
- }
-}
class DBGPerspective : public IDBGPerspective, public sigc::trackable {
//non copyable
@@ -538,18 +512,6 @@ public:
void open_file ();
- bool get_file_mime_type (const UString &a_path,
- UString &a_mime_type);
-
- bool setup_buffer_mime_and_lang
- (Glib::RefPtr<SourceBuffer> &a_buf,
- const std::string &a_mime_type = "text/x-c++") const;
-
- Glib::RefPtr<SourceBuffer> create_source_buffer () const;
-
- bool load_file (const UString &a_file,
- Glib::RefPtr<SourceBuffer> &a_source_buffer);
-
bool open_file (const UString &a_path, int current_line=-1);
SourceEditor* open_file_real (const UString &a_path, int current_line=-1);
@@ -571,21 +533,7 @@ public:
bool is_asm_title (const UString &);
- bool load_asm (const common::DisassembleInfo &a_info,
- const std::list<common::Asm> &a_asm,
- Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf);
-
bool read_file_line (const UString&, int, string&);
- bool write_asm_instr (std::ostringstream&,
- const common::AsmInstr&);
-
- bool write_asm_instr (std::ostringstream&,
- const common::Asm&);
-
- bool add_asm (const common::DisassembleInfo &a_info,
- const std::list<common::Asm> &a_asm,
- Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf,
- bool a_append = true);
SourceEditor* open_asm (const common::DisassembleInfo &a_info,
const std::list<common::Asm> &a_asm,
@@ -599,8 +547,7 @@ public:
SourceEditor *a_editor);
void pump_asm_including_address (SourceEditor *a_editor,
- const Address a_address,
- bool a_tight = false);
+ const Address a_address);
void switch_to_source_code ();
@@ -847,7 +794,7 @@ public:
void read_default_config ();
- vector<UString>& get_source_dirs ();
+ list<UString>& get_global_search_paths ();
bool find_file_in_source_dirs (const UString &a_file_name,
UString &a_file_path);
@@ -929,7 +876,8 @@ struct DBGPerspective::Priv {
vector<UString> prog_args;
UString prog_cwd;
map<UString, UString> env_variables;
- list<UString> search_paths;
+ list<UString> session_search_paths;
+ list<UString> global_search_paths;
map<UString, bool> paths_to_ignore;
Glib::RefPtr<Gnome::Glade::Xml> body_glade;
SafePtr<Gtk::Window> body_window;
@@ -1014,7 +962,6 @@ struct DBGPerspective::Priv {
ISessMgr::Session session;
IProcMgrSafePtr process_manager;
UString last_command_text;
- vector<UString> source_dirs;
bool show_dbg_errors;
bool use_system_font;
bool show_line_numbers;
@@ -1164,120 +1111,36 @@ struct DBGPerspective::Priv {
}
}
- bool is_buffer_valid_utf8 (const char *a_buffer,
- unsigned a_len)
- {
- RETURN_VAL_IF_FAIL (a_buffer, false);
- const char *end=0;
- bool is_valid = g_utf8_validate (a_buffer, a_len, &end);
- return is_valid;
- }
-
- //if source_buffer is not encoded in utf8, assume it is encoded
- //in the current user locale.
- //Try to convert it from user locale to utf8, and make sure the result
- //is valid. if not, throw an exception due to the fact the file is
- //encoded in an unknown encoding.
- bool ensure_buffer_is_in_utf8 (const UString &a_path,
- const std::string &a_input,
- UString &a_output,
- std::string &a_current_charset)
+ bool get_supported_encodings (list<string> &a_encodings)
{
- LOG_FUNCTION_SCOPE_NORMAL_DD;
- NEMIVER_TRY
+ list<UString> encodings;
+
+ NEMIVER_TRY;
- UString buf_content;
- if (is_buffer_valid_utf8 (a_input.c_str (), a_input.size ())) {
- a_output = a_input;
- return true;
- }
- UString utf8_content;
- bool converted=false;
- //get the list of candidate encodings that could be the encoding of
- //the a_input. This list is in gconf. So let's kindly ask gconf for
- //it. If for a reason we cannot reach gconf or the list is empty,
- //then we will fall back to a hardcoded list of encodings.
- THROW_IF_FAIL (workbench);
IConfMgrSafePtr conf_mgr = workbench->get_configuration_manager ();
- THROW_IF_FAIL (conf_mgr);
- std::list<UString> supported_encodings;
- bool have_gconf_values = false;
+ conf_mgr->get_key_value (CONF_KEY_SOURCE_FILE_ENCODING_LIST,
+ encodings);
- NEMIVER_TRY
- have_gconf_values =
- conf_mgr->get_key_value (CONF_KEY_SOURCE_FILE_ENCODING_LIST,
- supported_encodings);
- NEMIVER_CATCH_NOX
- if (have_gconf_values && !supported_encodings.empty ()) {
- LOG_DD ("trying encodings coming from gconf");
- std::list<UString>::const_iterator it;
- for (it = supported_encodings.begin ();
- it != supported_encodings.end ();
- ++it) {
- try {
- LOG_DD ("trying to convert buffer from encoding "
- << it->c_str ()
- << " to UTF-8");
- utf8_content =
- Glib::convert (a_input, "UTF-8",
- it->c_str ());
- } catch (Glib::Exception &e) {
- LOG_DD ("tentative encoding conversion failed!");
- continue;
- } catch (...) {
- THROW ("unknown exception raised by Glib::convert()");
- }
- LOG_DD ("tentative encoding conversion succeeded!");
- converted = true;
- break;
- }
- }
+ NEMIVER_CATCH_AND_RETURN (false);
- if (!converted) {
- //fall back to trying the hardcoded list of supported encodings
- LOG_DD ("trying hardcoded encodings");
- for (unsigned int i=0; i < SIZE_OF_SUPPORTED_ENCODINGS; i++) {
- try {
- utf8_content =
- Glib::convert (a_input,
- "UTF-8",
- SUPPORTED_ENCODINGS[i]);
- } catch (Glib::Exception &e) {
- continue;
- } catch (...) {
- THROW ("unknown exception raised by Glib::convert()");
- }
- converted = true;
- }
- }
- if (!converted) {
- THROW_IF_FAIL (!a_path.empty ());
- UString message;
- message.printf (_("File %s has an encoding that is not listed in "
- "the value of gconf key %s. "
- "Please add the encoding "
- "of that file to the values of the gconf "
- "key, and resume debugging"),
- a_path.c_str (),
- CONF_KEY_SOURCE_FILE_ENCODING_LIST);
- THROW (message);
- }
- const char *end=0;
- if (utf8_content.empty ()
- || !g_utf8_validate (utf8_content.raw ().c_str (),
- utf8_content.bytes (),
- &end)) {
- LOG_ERROR ("conversion from "
- << a_current_charset
- << " to utf8 failed");
- return false;
+ for (list<UString>::const_iterator it = encodings.begin ();
+ it != encodings.end ();
+ ++it) {
+ a_encodings.push_back (it->raw ());
}
- a_output = utf8_content;
-
- NEMIVER_CATCH_AND_RETURN (false)
+ return !encodings.empty ();
+ }
- return true;
+ bool load_file (const UString &a_path,
+ Glib::RefPtr<SourceBuffer> &a_buffer)
+ {
+ list<string> supported_encodings;
+ get_supported_encodings (supported_encodings);
+ return SourceEditor::load_file (a_path, supported_encodings,
+ enable_syntax_highlight,
+ a_buffer);
}
+
};//end struct DBGPerspective::Priv
enum ViewsIndex
@@ -2282,7 +2145,7 @@ DBGPerspective::on_conf_key_changed_signal (const UString &a_key,
NEMIVER_TRY
if (a_key == CONF_KEY_NEMIVER_SOURCE_DIRS) {
LOG_DD ("updated key source-dirs");
- m_priv->source_dirs = boost::get<UString> (a_value).split (":");
+ m_priv->global_search_paths = boost::get<UString> (a_value).split_to_list (":");
} else if (a_key == CONF_KEY_SHOW_DBG_ERROR_DIALOGS) {
m_priv->show_dbg_errors = boost::get<bool> (a_value);
} else if (a_key == CONF_KEY_SHOW_SOURCE_LINE_NUMBERS) {
@@ -4075,33 +3938,21 @@ DBGPerspective::clear_session_data ()
THROW_IF_FAIL (m_priv);
m_priv->env_variables.clear ();
- m_priv->search_paths.clear ();
+ m_priv->session_search_paths.clear ();
m_priv->breakpoints.clear ();
- m_priv->source_dirs.clear ();
+ m_priv->global_search_paths.clear ();
}
bool
DBGPerspective::find_absolute_path (const UString& a_file_path,
UString &a_absolute_path)
{
- // First, assume it's a full path name already.
- if (Glib::file_test (a_file_path, Glib::FILE_TEST_IS_REGULAR)) {
- a_absolute_path = a_file_path;
- return true;
- }
- // If that didn't work, look for a file of that name in the search
- // directories.
- if (find_file_in_source_dirs (a_file_path, a_absolute_path)) {
- return true;
- }
- // Then look for a file of that basename in the search directories.
- std::string basename =
- Glib::path_get_basename (Glib::filename_from_utf8 (a_file_path));
- if (basename != a_file_path
- && find_file_in_source_dirs (basename, a_absolute_path)) {
- return true;
- }
- return false;
+ return common::env::find_file_absolute_or_relative (a_file_path,
+ m_priv->prog_path,
+ m_priv->prog_cwd,
+ m_priv->session_search_paths,
+ m_priv->global_search_paths,
+ a_absolute_path);
}
/// Lookup a file path and return true if found. If the path is not
@@ -4120,25 +3971,14 @@ DBGPerspective::find_absolute_path_or_ask_user (const UString& a_file_path,
UString& a_absolute_path,
bool a_ignore_if_not_found)
{
- if (!find_absolute_path (a_file_path, a_absolute_path)) {
- if (m_priv->paths_to_ignore.find (a_file_path)
- != m_priv->paths_to_ignore.end ())
- // We didn't find a_file_path but as we were previously
- // requested to *not* ask the user to locate it, just
- // pretend we didn't find the file.
- return false;
- if (ask_user_to_select_file (a_file_path, a_absolute_path)) {
- UString parent_dir = Glib::filename_to_utf8
- (Glib::path_get_dirname (a_absolute_path));
- m_priv->search_paths.push_back (parent_dir);
- } else {
- if (a_ignore_if_not_found)
- // Don't ask the user to locate a_file_path next time.
- m_priv->paths_to_ignore[a_file_path] = true;
- return false;
- }
- }
- return true;
+ return ui_utils::find_absolute_path_or_ask_user (a_file_path,
+ m_priv->prog_path,
+ m_priv->prog_cwd,
+ m_priv->session_search_paths,
+ m_priv->global_search_paths,
+ m_priv->paths_to_ignore,
+ a_ignore_if_not_found,
+ a_absolute_path);
}
void
@@ -4462,7 +4302,8 @@ DBGPerspective::get_or_append_asm_source_editor ()
SourceEditor *source_editor =
get_source_editor_from_path (get_asm_title (), path);
if (source_editor == 0) {
- Glib::RefPtr<SourceBuffer> source_buffer = create_source_buffer ();
+ Glib::RefPtr<SourceBuffer> source_buffer =
+ SourceEditor::create_source_buffer ();
source_editor =
create_source_editor (source_buffer,
/*a_asm_view=*/true,
@@ -4812,16 +4653,16 @@ DBGPerspective::get_thread_list ()
return *m_priv->thread_list;
}
-vector<UString>&
-DBGPerspective::get_source_dirs ()
+list<UString>&
+DBGPerspective::get_global_search_paths ()
{
THROW_IF_FAIL (m_priv);
- if (m_priv->source_dirs.empty ()) {
+ if (m_priv->global_search_paths.empty ()) {
read_default_config ();
}
- return m_priv->source_dirs;
+ return m_priv->global_search_paths;
}
bool
@@ -4830,55 +4671,9 @@ DBGPerspective::find_file_in_source_dirs (const UString &a_file_name,
{
THROW_IF_FAIL (m_priv);
- string file_name = Glib::filename_from_utf8 (a_file_name),
- path,
- candidate;
- // first check if this is an absolute path
- if (Glib::path_is_absolute (file_name)) {
- if (Glib::file_test (file_name, Glib::FILE_TEST_IS_REGULAR)) {
- a_file_path = Glib::filename_to_utf8 (file_name);
- return true;
- }
- }
- // then look in the working directory
- candidate = Glib::build_filename (m_priv->prog_cwd, file_name);
- if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
- a_file_path = Glib::filename_to_utf8 (candidate);
- return true;
- }
- // then look in the directory of the binary
- candidate =
- Glib::build_filename (Glib::path_get_dirname (m_priv->prog_path),
- file_name);
- if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
- a_file_path = Glib::filename_to_utf8 (candidate);
- return true;
- }
- // then look in the session-specific search paths
- list<UString>::const_iterator session_iter;
- for (session_iter = m_priv->search_paths.begin ();
- session_iter != m_priv->search_paths.end ();
- ++session_iter) {
- path = Glib::filename_from_utf8 (*session_iter);
- candidate = Glib::build_filename (path, file_name);
- if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
- a_file_path = Glib::filename_to_utf8 (candidate);
- return true;
- }
- }
- // if not found, then look in the global search paths
- vector<UString>::const_iterator global_iter;
- for (global_iter = m_priv->source_dirs.begin ();
- global_iter != m_priv->source_dirs.end ();
- ++global_iter) {
- path = Glib::filename_from_utf8 (*global_iter);
- candidate = Glib::build_filename (path, file_name);
- if (Glib::file_test (candidate, Glib::FILE_TEST_IS_REGULAR)) {
- a_file_path = Glib::filename_to_utf8 (candidate);
- return true;
- }
- }
- return false;
+ return common::env::find_file (a_file_name, m_priv->prog_path,
+ m_priv->prog_cwd, m_priv->session_search_paths,
+ m_priv->global_search_paths, a_file_path);
}
bool
@@ -4958,7 +4753,7 @@ DBGPerspective::read_default_config ()
{
THROW_IF_FAIL (m_priv->workbench);
IConfMgr &conf_mgr = get_conf_mgr ();
- if (m_priv->source_dirs.empty ()) {
+ if (m_priv->global_search_paths.empty ()) {
UString dirs;
NEMIVER_TRY
@@ -4967,8 +4762,8 @@ DBGPerspective::read_default_config ()
LOG_DD ("got source dirs '" << dirs << "' from conf mgr");
if (!dirs.empty ()) {
- m_priv->source_dirs = dirs.split (":");
- LOG_DD ("that makes '" <<(int)m_priv->source_dirs.size()
+ m_priv->global_search_paths = dirs.split_to_list (":");
+ LOG_DD ("that makes '" <<(int)m_priv->global_search_paths.size()
<< "' dir paths");
}
@@ -5360,8 +5155,8 @@ DBGPerspective::record_and_save_session (ISessMgr::Session &a_session)
a_session.search_paths ().clear ();
list<UString>::const_iterator search_path_iter;
- for (search_path_iter = m_priv->search_paths.begin ();
- search_path_iter != m_priv->search_paths.end ();
+ for (search_path_iter = m_priv->session_search_paths.begin ();
+ search_path_iter != m_priv->session_search_paths.end ();
++search_path_iter) {
a_session.search_paths ().push_back (*search_path_iter);
}
@@ -5461,193 +5256,6 @@ DBGPerspective::edit_workbench_menu ()
//init_perspective_menu_entries ();
}
-bool
-DBGPerspective::get_file_mime_type (const UString &a_path,
- UString &a_mime_type)
-{
- NEMIVER_TRY
-
- std::string path = Glib::filename_from_utf8 (a_path);
-
-#ifdef WITH_GIO
- Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_path (path);
- THROW_IF_FAIL (gio_file);
-#else
- UString base_name = Glib::filename_to_utf8 (Glib::path_get_basename (path));
-#endif
-
- UString mime_type;
-#ifdef WITH_GIO
- Glib::RefPtr<Gio::FileInfo> info = gio_file->query_info();
- mime_type = Gio::content_type_get_mime_type(info->get_content_type ());
-#else
- mime_type = gnome_vfs_get_mime_type_for_name (base_name.c_str ());
-#endif
-
- if (mime_type == "") {
- mime_type = "text/x-c++";
- }
- LOG_DD ("file has mime type: " << mime_type);
- a_mime_type = mime_type;
- return true;
-
- NEMIVER_CATCH_AND_RETURN (false)
-}
-
-// Make sure the source buffer a_buf is properly setup to have the mime
-// type a_mime_type. If a_buf is null, a new one is created.
-// Returns true upon successful completion, false otherwise.
-bool
-DBGPerspective::setup_buffer_mime_and_lang (Glib::RefPtr<SourceBuffer> &a_buf,
- const std::string &a_mime_type) const
-{
- NEMIVER_TRY
-
-#ifdef WITH_SOURCEVIEWMM2
- Glib::RefPtr<SourceLanguageManager> lang_manager =
- SourceLanguageManager::get_default ();
-#else
- Glib::RefPtr<SourceLanguagesManager> lang_manager =
- SourceLanguagesManager::create ();
-#endif // WITH_SOURCEVIEWMM2
- Glib::RefPtr<SourceLanguage> lang;
-#ifdef WITH_SOURCEVIEWMM2
- std::list<Glib::ustring> lang_ids = lang_manager->get_language_ids ();
- for (std::list<Glib::ustring>::const_iterator it = lang_ids.begin ();
- it != lang_ids.end ();
- ++it) {
- Glib::RefPtr<gtksourceview::SourceLanguage> candidate =
- lang_manager->get_language (*it);
- std::list<Glib::ustring> mime_types = candidate->get_mime_types ();
- std::list<Glib::ustring>::const_iterator mime_it;
- for (mime_it = mime_types.begin ();
- mime_it != mime_types.end ();
- ++mime_it) {
- if (*mime_it == a_mime_type) {
- // one of the mime types associated with this language matches
- // the mime type of our file, so use this language
- lang = candidate;
- break; // no need to look at further mime types
- }
- }
- // we found a matching language, so stop looking for other languages
- if (lang) break;
- }
-#else
- lang = lang_manager->get_language_from_mime_type (mime_type);
-#endif // WITH_SOURCEVIEWMM2
-
- if (!a_buf)
- a_buf = SourceBuffer::create (lang);
- else {
- a_buf->set_language (lang);
- a_buf->erase (a_buf->begin (), a_buf->end ());
- }
- THROW_IF_FAIL (a_buf);
- return true;
-
- NEMIVER_CATCH_AND_RETURN (false);
-}
-
-/// Create a source buffer properly set up to contain/highlight c++
-/// code.
-/// \return the created buffer or nil if something bad happened.
-Glib::RefPtr<SourceBuffer>
-DBGPerspective::create_source_buffer () const
-{
- Glib::RefPtr<SourceBuffer> result;
- setup_buffer_mime_and_lang (result);
- return result;
-}
-
-bool
-DBGPerspective::load_file (const UString &a_path,
- Glib::RefPtr<SourceBuffer> &a_source_buffer)
-{
- NEMIVER_TRY
-
- std::string path = Glib::filename_from_utf8 (a_path);
-#ifdef WITH_GIO
- Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_path (path);
- THROW_IF_FAIL (gio_file);
- if (!gio_file->query_exists ()) {
-#else
- ifstream file (path.c_str ());
- if (!file.good () && !file.eof ()) {
-#endif
- LOG_ERROR ("Could not open file " + path);
- ui_utils::display_error ("Could not open file: "
- + Glib::filename_to_utf8 (path));
- return false;
- }
-
- UString mime_type;
- if (!get_file_mime_type (path, mime_type)) {
- LOG_ERROR ("Could not get mime type for " + path);
- return false;
- }
-
- if (!setup_buffer_mime_and_lang (a_source_buffer, mime_type)) {
- LOG_ERROR ("Could not setup source buffer mime type or language");
- return false;
- }
- THROW_IF_FAIL (a_source_buffer);
-
- gint buf_size = 10 * 1024;
- CharSafePtr buf (new gchar [buf_size + 1]);
- memset (buf.get (), 0, buf_size + 1);
-
- unsigned nb_bytes=0;
- std::string content;
-#ifdef WITH_GIO
- Glib::RefPtr<Gio::FileInputStream> gio_stream = gio_file->read ();
- THROW_IF_FAIL (gio_stream);
- gssize bytes_read = 0;
- for (;;) {
- bytes_read = gio_stream->read (buf.get (), buf_size);
- content.append (buf.get (), bytes_read);
- nb_bytes += bytes_read;
- if (bytes_read != buf_size) {break;}
- }
- gio_stream->close ();
-#else
- for (;;) {
- file.read (buf.get (), buf_size);
- content.append (buf.get (), file.gcount ());
- THROW_IF_FAIL (file.good () || file.eof ());
- nb_bytes += file.gcount ();
- if (file.gcount () != buf_size) {break;}
- }
- file.close ();
-#endif // WITH_GIO
- UString utf8_content;
- std::string cur_charset;
- if (!m_priv->ensure_buffer_is_in_utf8 (a_path,
- content,
- utf8_content,
- cur_charset)) {
- UString msg;
- msg.printf (_("Could not load file %s because its encoding "
- "is different from %s"),
- path.c_str (),
- cur_charset.c_str ());
- ui_utils::display_error (msg);
- return false;
- }
- a_source_buffer->set_text (utf8_content);
- LOG_DD ("file loaded. Read " << (int)nb_bytes << " bytes");
-
-#ifdef WITH_SOURCEVIEWMM2
- a_source_buffer->set_highlight_syntax (m_priv->enable_syntax_highlight);
-#else
- a_source_buffer->set_highlight (m_priv->enable_syntax_highlight);
-#endif // WITH_SOURCEVIEWMM2
-
- NEMIVER_CATCH_AND_RETURN (false);
-
- return true;
-}
-
SourceEditor*
DBGPerspective::create_source_editor (Glib::RefPtr<SourceBuffer> &a_source_buf,
bool a_asm_view,
@@ -5775,9 +5383,8 @@ DBGPerspective::open_file_real (const UString &a_path,
NEMIVER_TRY
Glib::RefPtr<SourceBuffer> source_buffer;
- if (!load_file (a_path, source_buffer)) {
+ if (!m_priv->load_file (a_path, source_buffer))
return 0;
- }
source_editor = create_source_editor (source_buffer,
/*a_asm_view=*/false,
@@ -5870,224 +5477,6 @@ DBGPerspective::is_asm_title (const UString &a_path)
return (a_path.raw () == DISASSEMBLY_TITLE);
}
-bool
-DBGPerspective::load_asm (const common::DisassembleInfo &a_info,
- const std::list<common::Asm> &a_asm,
- Glib::RefPtr<SourceBuffer> &a_source_buffer)
-{
- LOG_FUNCTION_SCOPE_NORMAL_DD;
-
- NEMIVER_TRY
-
- std::string mime_type = "text/x-asm";
- if (!setup_buffer_mime_and_lang (a_source_buffer, mime_type)) {
- LOG_ERROR ("Could not setup source buffer mime type of language");
- return false;
- }
- THROW_IF_FAIL (a_source_buffer);
-
- add_asm (a_info, a_asm, a_source_buffer, /*append=*/ true);
-
- NEMIVER_CATCH_AND_RETURN (false)
- return true;
-}
-
-/// Given a file path P and a line number N , reads the line N from P
-/// and return it iff the function returns true. This is useful
-/// e.g. when forging a mixed source/assembly source view, and we want
-/// to display a source line N from a file P.
-///
-/// \param a_file_path the file path to consider
-/// \param a_line_number the line number to consider
-/// \param a_line the string containing the resulting line read, if
-/// and only if the function returned true.
-/// \return true upon successful completion, false otherwise.
-bool
-DBGPerspective::read_file_line (const UString &a_file_path,
- int a_line_number,
- string &a_line)
-{
- if (a_file_path.empty ())
- return false;
-
- UString path;
- if (!find_absolute_path_or_ask_user (a_file_path, path))
- return false;
- bool found_line = false;
- int line_num = 1;
- char c = 0;
-
- NEMIVER_TRY
-
- std::ifstream file (path.c_str ());
-
- if (!file.good ()) {
- LOG_ERROR ("Could not open file " + path);
- return false;
- }
-
- while (true) {
- if (line_num == a_line_number) {
- found_line = true;
- break;
- }
- file.get (c);
- if (!file.good ())
- break;
- if (c == '\n')
- ++line_num;
- }
- if (found_line) {
- a_line.clear ();
- while (true) {
- file.get (c);
- if (!file.good ())
- break;
- if (c == '\n')
- break;
- a_line += c;
- }
- }
- file.close ();
-
- NEMIVER_CATCH
-
- return found_line;
-}
-
-bool
-DBGPerspective::write_asm_instr (std::ostringstream &a_os,
- const common::AsmInstr &a_instr)
-{
- a_os << a_instr.address ();
- a_os << " ";
- a_os << "<" << a_instr.function ();
- if (!a_instr.offset ().empty () && a_instr.offset () != "0")
- a_os << "+" << a_instr.offset ();
- a_os << ">: ";
- a_os << a_instr.instruction ();
-
- return true;
-}
-
-bool
-DBGPerspective::write_asm_instr (std::ostringstream &a_os,
- const common::Asm &a_asm)
-{
- bool written = false;
-
- switch (a_asm.which ()) {
- case common::Asm::TYPE_PURE:
- write_asm_instr (a_os, a_asm.instr ());
- written = true;
- break;
- case common::Asm::TYPE_MIXED: {
- const common::MixedAsmInstr &instr = a_asm.mixed_instr ();
- // Ignore requests for line 0. Line 0 cannot exist as lines
- // should be starting at 1., some
- // versions of GDB seem to be referencing it for a reason.
- if (instr.line_number () == 0) {
- LOG_DD ("Skipping asm instr at line 0");
- return false;
- }
- string line;
- if (read_file_line (instr.file_path (),
- instr.line_number (),
- line)) {
- if (line.empty ())
- a_os << "\n";
- else {
- a_os << line; // line does not end with a '\n' char.
- written = true;
- }
- } else {
- a_os << "<src file=\""
- << instr.file_path ()
- << "\" line=\""
- << instr.line_number ()
- << "\"/>";
- written = true;
- }
-
- if (!instr.instrs ().empty ()) {
- list<common::AsmInstr>::const_iterator it =
- instr.instrs ().begin ();
- if (it != instr.instrs ().end ()) {
- if (written)
- a_os << "\n";
- written = write_asm_instr (a_os, *it);
- ++it;
- }
- for (; it != instr.instrs ().end (); ++it) {
- if (written)
- a_os << "\n";
- written = write_asm_instr (a_os, *it);
- }
- }
- }
- break;
- default:
- break;
- }
- return written;
-}
-
-bool
-DBGPerspective::add_asm (const common::DisassembleInfo &/*a_info*/,
- const std::list<common::Asm> &a_asm,
- Glib::RefPtr<SourceBuffer> &a_buf,
- bool a_append)
-{
- LOG_FUNCTION_SCOPE_NORMAL_DD;
-
- if (!a_buf)
- return false;
-
- log_asm_insns (a_asm);
-
- std::list<common::Asm>::const_iterator it = a_asm.begin ();
- if (it == a_asm.end ())
- return true;
-
- // Write the first asm instruction into a string stream.
- std::ostringstream first_os, endl_os;
- bool first_written = write_asm_instr (first_os, *it);
- endl_os << std::endl;
-
- // Figure out where to insert the asm instrs, depending on a_append
- // (either prepend or append it)
- // Also, if a_buf is not empty and we are going to append asm
- // instrs, make sure to add an "end line" before appending our asm
- // instrs.
- Gtk::TextBuffer::iterator insert_it;
- if (a_append) {
- insert_it = a_buf->end ();
- if (a_buf->get_char_count () != 0) {
- insert_it = a_buf->insert (insert_it, endl_os.str ());
- }
- } else {
- insert_it = a_buf->begin ();
- }
- // Really insert the the first asm instrs.
- if (first_written)
- insert_it = a_buf->insert (insert_it, first_os.str ());
-
- // Append the remaining asm instrs. Make sure to add an "end of line"
- // before each asm instr.
- bool prev_written = true;
- for (++it; it != a_asm.end (); ++it) {
- // If the first item was empty, do not insert "\n" on the first
- // iteration.
- if (first_written && prev_written)
- insert_it = a_buf->insert (insert_it, endl_os.str ());
- first_written = true;
- ostringstream os;
- prev_written = write_asm_instr (os, *it);
- insert_it = a_buf->insert (insert_it, os.str ());
- }
- return true;
-}
-
// If no asm dedicated tab was already present in the perspective,
// create a new one, otherwise reuse the one that was already present.
// Then load the assembly insns a_asm described by a_info into the
@@ -6112,7 +5501,12 @@ DBGPerspective::open_asm (const common::DisassembleInfo &a_info,
source_buffer->erase (source_buffer->begin (), source_buffer->end ());
}
- if (load_asm (a_info, a_asm, source_buffer) == 0)
+ if (!SourceEditor::load_asm (a_info, a_asm, /*a_append=*/true,
+ m_priv->prog_path, m_priv->prog_cwd,
+ m_priv->session_search_paths,
+ m_priv->global_search_paths,
+ m_priv->paths_to_ignore,
+ source_buffer))
return 0;
if (!source_editor)
@@ -6161,12 +5555,16 @@ DBGPerspective::switch_to_asm (const common::DisassembleInfo &a_info,
Glib::RefPtr<SourceBuffer> asm_buf;
if ((asm_buf = a_source_editor->get_assembly_source_buffer ()) == 0) {
- setup_buffer_mime_and_lang (asm_buf, "test/x-asm");
+ SourceEditor::setup_buffer_mime_and_lang (asm_buf, "test/x-asm");
a_source_editor->register_assembly_source_buffer (asm_buf);
asm_buf = a_source_editor->get_assembly_source_buffer ();
RETURN_IF_FAIL (asm_buf);
}
- if (!load_asm (a_info, a_asm, asm_buf)) {
+ if (!SourceEditor::load_asm (a_info, a_asm, /*a_append=*/true,
+ m_priv->prog_path, m_priv->prog_cwd,
+ m_priv->session_search_paths,
+ m_priv->global_search_paths,
+ m_priv->paths_to_ignore, asm_buf)) {
LOG_ERROR ("failed to load asm");
return;
}
@@ -6241,9 +5639,9 @@ DBGPerspective::switch_to_source_code ()
<< m_priv->current_frame.file_name ());
return;
}
- get_file_mime_type (absolute_path, mime_type);
- setup_buffer_mime_and_lang (source_buf, mime_type);
- load_file (absolute_path, source_buf);
+ SourceEditor::get_file_mime_type (absolute_path, mime_type);
+ SourceEditor::setup_buffer_mime_and_lang (source_buf, mime_type);
+ m_priv->load_file (absolute_path, source_buf);
source_editor->register_non_assembly_source_buffer (source_buf);
}
source_editor->switch_to_non_assembly_source_buffer ();
@@ -6342,7 +5740,8 @@ DBGPerspective::reload_file (const UString &a_path)
editor->source_view ().get_source_buffer ();
int current_line = editor->current_line ();
int current_column = editor->current_column ();
- if (!load_file (a_path, buffer))
+
+ if (!m_priv->load_file (a_path, buffer))
return false;
editor->register_non_assembly_source_buffer (buffer);
editor->current_line (current_line);
@@ -6415,11 +5814,11 @@ DBGPerspective::execute_session (ISessMgr::Session &a_session)
// populate the list of search paths from the current session
list<UString>::const_iterator path_iter;
- m_priv->search_paths.clear();
+ m_priv->session_search_paths.clear();
for (path_iter = m_priv->session.search_paths ().begin ();
path_iter != m_priv->session.search_paths ().end ();
++path_iter) {
- m_priv->search_paths.push_back (*path_iter);
+ m_priv->session_search_paths.push_back (*path_iter);
}
// open the previously opened files
@@ -7161,26 +6560,8 @@ bool
DBGPerspective::ask_user_to_select_file (const UString &a_file_name,
UString &a_selected_file_path)
{
- LocateFileDialog dialog (plugin_path (), a_file_name);
- // start looking in the working directory
- dialog.file_location (m_priv->prog_cwd);
- int result = dialog.run ();
- if (result == Gtk::RESPONSE_OK) {
- UString file_path = dialog.file_location ();
- if (!Glib::file_test (file_path, Glib::FILE_TEST_IS_REGULAR)
- || (Glib::path_get_basename (a_file_name)
- != Glib::path_get_basename (file_path)))
- return false;
- UString parent_dir =
- Glib::filename_to_utf8 (Glib::path_get_dirname
- (dialog.file_location ()));
- if (!Glib::file_test (parent_dir, Glib::FILE_TEST_IS_DIR))
- return false;
-
- a_selected_file_path = file_path;
- return true;
- }
- return false;
+ return ui_utils::ask_user_to_select_file (a_file_name, m_priv->prog_cwd,
+ a_selected_file_path);
}
bool
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.h b/src/persp/dbgperspective/nmv-dbg-perspective.h
index dfeb5d6..72d3258 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.h
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.h
@@ -73,10 +73,6 @@ public:
virtual void close_file (const UString &a_uri) = 0;
- virtual bool load_asm (const common::DisassembleInfo &a_info,
- const std::list<common::Asm> &a_asm,
- Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf) = 0;
-
virtual Gtk::Widget* load_menu (const UString &a_filename,
const UString &a_widget_name) = 0;
diff --git a/src/uicommon/Makefile.am b/src/uicommon/Makefile.am
index f3358b1..9bbe4e9 100644
--- a/src/uicommon/Makefile.am
+++ b/src/uicommon/Makefile.am
@@ -4,6 +4,10 @@ sources = \
$(public_headers) \
nmv-ui-utils.h \
nmv-ui-utils.cc \
+nmv-dialog.cc \
+nmv-dialog.h \
+nmv-locate-file-dialog.cc \
+nmv-locate-file-dialog.h \
ephy-spinner.c \
ephy-spinner.h \
ephy-spinner-tool-item.c \
diff --git a/src/persp/dbgperspective/nmv-dialog.cc b/src/uicommon/nmv-dialog.cc
similarity index 82%
rename from src/persp/dbgperspective/nmv-dialog.cc
rename to src/uicommon/nmv-dialog.cc
index 9c12f25..2f60efb 100644
--- a/src/persp/dbgperspective/nmv-dialog.cc
+++ b/src/uicommon/nmv-dialog.cc
@@ -47,14 +47,25 @@ public:
const UString &a_glade_filename,
const UString &a_widget_name)
{
- vector<string> path_elems;
- path_elems.push_back (Glib::locale_from_utf8 (a_resource_root_path));
- path_elems.push_back ("glade");
- path_elems.push_back (a_glade_filename);
- string glade_path = Glib::build_filename (path_elems);
+ string glade_path;
+ if (!a_resource_root_path.empty ()) {
+ // So the glade file is shipped within a plugin. Build the
+ // path to it accordingly.
+ vector<string> path_elems;
+ path_elems.push_back (Glib::locale_from_utf8 (a_resource_root_path));
+ path_elems.push_back ("glade");
+ path_elems.push_back (a_glade_filename);
+ glade_path = Glib::build_filename (path_elems);
+ } else {
+ // THe glade file is shipped into the global nemiver glade
+ // directories.
+ glade_path = env::build_path_to_glade_file (a_glade_filename);
+ }
+
if (!Glib::file_test (glade_path, Glib::FILE_TEST_IS_REGULAR)) {
THROW (UString ("could not find file ") + glade_path);
}
+
glade = Gnome::Glade::Xml::create (glade_path);
THROW_IF_FAIL (glade);
dialog.reset
diff --git a/src/persp/dbgperspective/nmv-dialog.h b/src/uicommon/nmv-dialog.h
similarity index 100%
rename from src/persp/dbgperspective/nmv-dialog.h
rename to src/uicommon/nmv-dialog.h
diff --git a/src/persp/dbgperspective/nmv-locate-file-dialog.cc b/src/uicommon/nmv-locate-file-dialog.cc
similarity index 100%
rename from src/persp/dbgperspective/nmv-locate-file-dialog.cc
rename to src/uicommon/nmv-locate-file-dialog.cc
diff --git a/src/persp/dbgperspective/nmv-locate-file-dialog.h b/src/uicommon/nmv-locate-file-dialog.h
similarity index 100%
rename from src/persp/dbgperspective/nmv-locate-file-dialog.h
rename to src/uicommon/nmv-locate-file-dialog.h
diff --git a/src/uicommon/nmv-source-editor.cc b/src/uicommon/nmv-source-editor.cc
index d1c3ce7..06e0d45 100644
--- a/src/uicommon/nmv-source-editor.cc
+++ b/src/uicommon/nmv-source-editor.cc
@@ -30,9 +30,25 @@
#include <gtkmm/scrolledwindow.h>
#include <gtksourceviewmm/sourcemark.h>
#include <gtksourceviewmm/sourceiter.h>
+#ifdef WITH_SOURCEVIEWMM2
+#include <gtksourceviewmm/sourcelanguagemanager.h>
+#include <gtksourceviewmm/sourcestyleschememanager.h>
+#else
+#include <gtksourceviewmm/sourcelanguagesmanager.h>
+#endif // WITH_SOURCEVIEWMM2
+#ifdef WITH_GIO
+#include <giomm/file.h>
+#include <giomm/contenttype.h>
+#else
+#include <libgnomevfs/gnome-vfs-mime-utils.h>
+#include <libgnomevfs/gnome-vfs-monitor.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#endif // WITH_GIO
#include "common/nmv-exception.h"
#include "common/nmv-sequence.h"
#include "common/nmv-str-utils.h"
+#include "common/nmv-asm-utils.h"
#include "uicommon/nmv-ui-utils.h"
#include "nmv-source-editor.h"
@@ -41,9 +57,10 @@ using namespace nemiver::common;
using gtksourceview::SourceMark;
using gtksourceview::SourceIter;
using gtksourceview::SearchFlags;
+using gtksourceview::SourceLanguage;
+using gtksourceview::SourceLanguageManager;
-namespace nemiver
-{
+NEMIVER_BEGIN_NAMESPACE (nemiver)
const char* BREAKPOINT_ENABLED_CATEGORY = "breakpoint-enabled-category";
const char* BREAKPOINT_DISABLED_CATEGORY = "breakpoint-disabled-category";
@@ -1087,6 +1104,294 @@ SourceEditor::do_search (const UString &a_str,
return false;
}
+/// Guess the mime type of a file.
+/// \param a_path the path of the file to consider.
+/// \param a_mime_type the resulting mime type, set iff the function
+/// returns true.
+/// \return true upon successful completion, false otherwise.
+bool
+SourceEditor::get_file_mime_type (const UString &a_path,
+ UString &a_mime_type)
+{
+ NEMIVER_TRY
+
+ std::string path = Glib::filename_from_utf8 (a_path);
+
+#ifdef WITH_GIO
+ Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_path (path);
+ THROW_IF_FAIL (gio_file);
+#else
+ UString base_name = Glib::filename_to_utf8 (Glib::path_get_basename (path));
+#endif
+
+ UString mime_type;
+#ifdef WITH_GIO
+ Glib::RefPtr<Gio::FileInfo> info = gio_file->query_info();
+ mime_type = Gio::content_type_get_mime_type(info->get_content_type ());
+#else
+ mime_type = gnome_vfs_get_mime_type_for_name (base_name.c_str ());
+#endif
+
+ if (mime_type == "") {
+ mime_type = "text/x-c++";
+ }
+ LOG_DD ("file has mime type: " << mime_type);
+ a_mime_type = mime_type;
+ return true;
+
+ NEMIVER_CATCH_AND_RETURN (false)
+}
+
+/// Make sure the source buffer a_buf is properly setup to have the
+/// mime type a_mime_type. If a_buf is null, a new one is created.
+/// Returns true upon successful completion, false otherwise.
+bool
+SourceEditor::setup_buffer_mime_and_lang (Glib::RefPtr<SourceBuffer> &a_buf,
+ const std::string &a_mime_type)
+{
+ NEMIVER_TRY
+
+#ifdef WITH_SOURCEVIEWMM2
+ Glib::RefPtr<SourceLanguageManager> lang_manager =
+ SourceLanguageManager::get_default ();
+#else
+ Glib::RefPtr<SourceLanguagesManager> lang_manager =
+ SourceLanguagesManager::create ();
+#endif // WITH_SOURCEVIEWMM2
+ Glib::RefPtr<SourceLanguage> lang;
+ #ifdef WITH_SOURCEVIEWMM2
+ std::list<Glib::ustring> lang_ids = lang_manager->get_language_ids ();
+ for (std::list<Glib::ustring>::const_iterator it = lang_ids.begin ();
+ it != lang_ids.end ();
+ ++it) {
+ Glib::RefPtr<gtksourceview::SourceLanguage> candidate =
+ lang_manager->get_language (*it);
+ std::list<Glib::ustring> mime_types = candidate->get_mime_types ();
+ std::list<Glib::ustring>::const_iterator mime_it;
+ for (mime_it = mime_types.begin ();
+ mime_it != mime_types.end ();
+ ++mime_it) {
+ if (*mime_it == a_mime_type) {
+ // one of the mime types associated with this language matches
+ // the mime type of our file, so use this language
+ lang = candidate;
+ break; // no need to look at further mime types
+ }
+ }
+ // we found a matching language, so stop looking for other languages
+ if (lang) break;
+ }
+#else
+ lang = lang_manager->get_language_from_mime_type (mime_type);
+#endif // WITH_SOURCEVIEWMM2
+
+ if (!a_buf)
+ a_buf = SourceBuffer::create (lang);
+ else {
+ a_buf->set_language (lang);
+ a_buf->erase (a_buf->begin (), a_buf->end ());
+ }
+ THROW_IF_FAIL (a_buf);
+ return true;
+
+ NEMIVER_CATCH_AND_RETURN (false);
+}
+
+/// Create a source buffer properly set up to contain/highlight c++
+/// code.
+/// \return the created buffer or nil if something bad happened.
+Glib::RefPtr<SourceBuffer>
+SourceEditor::create_source_buffer ()
+{
+ Glib::RefPtr<SourceBuffer> result;
+ setup_buffer_mime_and_lang (result);
+ return result;
+}
+
+bool
+SourceEditor::load_file (const UString &a_path,
+ const std::list<std::string> &a_supported_encodings,
+ bool a_enable_syntax_highlight,
+ Glib::RefPtr<SourceBuffer> &a_source_buffer)
+{
+ NEMIVER_TRY;
+
+ std::string path = Glib::filename_from_utf8 (a_path);
+#ifdef WITH_GIO
+ Glib::RefPtr<Gio::File> gio_file = Gio::File::create_for_path (path);
+ THROW_IF_FAIL (gio_file);
+ #define FILE_IS_OK (!gio_file->query_exists ())
+#else
+ ifstream file (path.c_str ());
+ #define FILE_IS_OK (!file.good () && !file.eof ())
+
+#endif
+ if (FILE_IS_OK) {
+ LOG_ERROR ("Could not open file " + path);
+ ui_utils::display_error ("Could not open file: "
+ + Glib::filename_to_utf8 (path));
+ return false;
+ }
+
+ UString mime_type;
+ if (!get_file_mime_type (path, mime_type)) {
+ LOG_ERROR ("Could not get mime type for " + path);
+ return false;
+ }
+
+ if (!setup_buffer_mime_and_lang (a_source_buffer, mime_type)) {
+ LOG_ERROR ("Could not setup source buffer mime type or language");
+ return false;
+ }
+ THROW_IF_FAIL (a_source_buffer);
+
+ gint buf_size = 10 * 1024;
+ CharSafePtr buf (new gchar [buf_size + 1]);
+ memset (buf.get (), 0, buf_size + 1);
+
+ unsigned nb_bytes=0;
+ std::string content;
+#ifdef WITH_GIO
+ Glib::RefPtr<Gio::FileInputStream> gio_stream = gio_file->read ();
+ THROW_IF_FAIL (gio_stream);
+ gssize bytes_read = 0;
+ for (;;) {
+ bytes_read = gio_stream->read (buf.get (), buf_size);
+ content.append (buf.get (), bytes_read);
+ nb_bytes += bytes_read;
+ if (bytes_read != buf_size) {break;}
+ }
+ gio_stream->close ();
+#else
+ for (;;) {
+ file.read (buf.get (), buf_size);
+ content.append (buf.get (), file.gcount ());
+ THROW_IF_FAIL (file.good () || file.eof ());
+ nb_bytes += file.gcount ();
+ if (file.gcount () != buf_size) {break;}
+ }
+ file.close ();
+#endif // WITH_GIO
+ UString utf8_content;
+ std::string cur_charset;
+ if (!str_utils::ensure_buffer_is_in_utf8 (content,
+ a_supported_encodings,
+ utf8_content)) {
+ UString msg;
+ msg.printf (_("Could not load file %s because its encoding "
+ "is different from %s"),
+ path.c_str (),
+ cur_charset.c_str ());
+ ui_utils::display_error (msg);
+ return false;
+ }
+ a_source_buffer->set_text (utf8_content);
+ LOG_DD ("file loaded. Read " << (int)nb_bytes << " bytes");
+
+#ifdef WITH_SOURCEVIEWMM2
+ a_source_buffer->set_highlight_syntax (a_enable_syntax_highlight);
+#else
+ a_source_buffer->set_highlight (a_enable_syntax_highlight);
+#endif // WITH_SOURCEVIEWMM2
+
+ NEMIVER_CATCH_AND_RETURN (false);
+
+ return true;
+}
+
+bool
+SourceEditor::add_asm (const common::DisassembleInfo &/*a_info*/,
+ const std::list<common::Asm> &a_asm,
+ bool a_append,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_session_dirs,
+ const list<UString> &a_glob_dirs,
+ std::map<UString, bool> &a_ignore_paths,
+ Glib::RefPtr<SourceBuffer> &a_buf)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ if (!a_buf)
+ return false;
+
+ nemiver::common::log_asm_insns (a_asm);
+
+ std::list<common::Asm>::const_iterator it = a_asm.begin ();
+ if (it == a_asm.end ())
+ return true;
+
+ // Write the first asm instruction into a string stream.
+ std::ostringstream first_os, endl_os;
+ ReadLine reader (a_prog_path, a_cwd, a_session_dirs, a_glob_dirs,
+ a_ignore_paths, &ui_utils::find_file_and_read_line);
+ bool first_written = write_asm_instr (*it, reader, first_os);
+ endl_os << std::endl;
+
+ // Figure out where to insert the asm instrs, depending on a_append
+ // (either prepend or append it)
+ // Also, if a_buf is not empty and we are going to append asm
+ // instrs, make sure to add an "end line" before appending our asm
+ // instrs.
+ Gtk::TextBuffer::iterator insert_it;
+ if (a_append) {
+ insert_it = a_buf->end ();
+ if (a_buf->get_char_count () != 0) {
+ insert_it = a_buf->insert (insert_it, endl_os.str ());
+ }
+ } else {
+ insert_it = a_buf->begin ();
+ }
+ // Really insert the the first asm instrs.
+ if (first_written)
+ insert_it = a_buf->insert (insert_it, first_os.str ());
+
+ // Append the remaining asm instrs. Make sure to add an "end of line"
+ // before each asm instr.
+ bool prev_written = true;
+ for (++it; it != a_asm.end (); ++it) {
+ // If the first item was empty, do not insert "\n" on the first
+ // iteration.
+ if (first_written && prev_written)
+ insert_it = a_buf->insert (insert_it, endl_os.str ());
+ first_written = true;
+ ostringstream os;
+ prev_written = write_asm_instr (*it, reader, os);
+ insert_it = a_buf->insert (insert_it, os.str ());
+ }
+ return true;
+}
+
+bool
+SourceEditor::load_asm (const common::DisassembleInfo &a_info,
+ const std::list<common::Asm> &a_asm,
+ bool a_append,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_session_dirs,
+ const list<UString> &a_glob_dirs,
+ std::map<UString, bool> &a_ignore_paths,
+ Glib::RefPtr<SourceBuffer> &a_buf)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY
+
+ std::string mime_type = "text/x-asm";
+ if (!setup_buffer_mime_and_lang (a_buf, mime_type)) {
+ LOG_ERROR ("Could not setup source buffer mime type of language");
+ return false;
+ }
+ THROW_IF_FAIL (a_buf);
+
+ add_asm (a_info, a_asm, a_append, a_prog_path, a_cwd,
+ a_session_dirs, a_glob_dirs, a_ignore_paths,
+ a_buf);
+
+ NEMIVER_CATCH_AND_RETURN (false)
+ return true;
+}
+
/// Registers a assembly source buffer
/// \param a_buf the assembly source buffer
void
@@ -1270,5 +1575,4 @@ SourceEditor::insertion_changed_signal () const
return m_priv->insertion_changed_signal;
}
-}//end namespace nemiver
-
+NEMIVER_END_NAMESPACE (nemiver)
diff --git a/src/uicommon/nmv-source-editor.h b/src/uicommon/nmv-source-editor.h
index 8a9163d..0c3f2c9 100644
--- a/src/uicommon/nmv-source-editor.h
+++ b/src/uicommon/nmv-source-editor.h
@@ -27,12 +27,14 @@
#include <list>
#include <functional>
+#include <map>
#include <gtkmm/box.h>
#include <gtksourceviewmm/sourceview.h>
#include "common/nmv-safe-ptr-utils.h"
#include "common/nmv-ustring.h"
#include "common/nmv-address.h"
#include "common/nmv-range.h"
+#include "common/nmv-asm-instr.h"
using gtksourceview::SourceView;
using gtksourceview::SourceBuffer;
@@ -41,6 +43,7 @@ using nemiver::common::SafePtr;
using nemiver::common::UString;
using nemiver::common::Address;
using std::list;
+using std::map;
namespace nemiver {
@@ -105,6 +108,20 @@ public:
bool a_search_backwards=false,
bool a_clear_selection=false);
+ static bool get_file_mime_type (const UString &a_path,
+ UString &a_mime_type);
+
+ static bool setup_buffer_mime_and_lang (Glib::RefPtr<SourceBuffer> &a_buf,
+ const std::string &a_mime_type =
+ "text/x-c++");
+
+ static Glib::RefPtr<SourceBuffer> create_source_buffer ();
+
+ static bool load_file (const UString &a_path,
+ const std::list<std::string> &a_supported_encodings,
+ bool a_enable_syntaxt_highlight,
+ Glib::RefPtr<SourceBuffer> &a_source_buffer);
+
/// \name Assembly source buffer handling.
/// @{
@@ -148,6 +165,27 @@ public:
bool remove_visual_breakpoint_from_address (const Address &);
bool scroll_to_address (const Address &a_address);
+ static bool add_asm (const common::DisassembleInfo &/*a_info*/,
+ const std::list<common::Asm> &a_asm,
+ bool a_append,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_session_dirs,
+ const list<UString> &a_glob_dirs,
+ std::map<UString, bool> &a_ignore_paths,
+ Glib::RefPtr<SourceBuffer> &a_buf);
+
+ static bool load_asm (const common::DisassembleInfo &/*a_info*/,
+ const std::list<common::Asm> &a_asm,
+ bool a_append,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_session_dirs,
+ const list<UString> &a_glob_dirs,
+ std::map<UString, bool> &a_ignore_paths,
+ Glib::RefPtr<SourceBuffer> &a_buf);
+
+
/// @}
/// \name signals
diff --git a/src/uicommon/nmv-ui-utils.cc b/src/uicommon/nmv-ui-utils.cc
index 0a18ea0..586a680 100644
--- a/src/uicommon/nmv-ui-utils.cc
+++ b/src/uicommon/nmv-ui-utils.cc
@@ -24,9 +24,11 @@
*
*See COPYRIGHT file copyright information.
*/
+#include <glib/gi18n.h>
#include "common/nmv-exception.h"
#include "nmv-ui-utils.h"
-#include <glib/gi18n.h>
+#include "nmv-locate-file-dialog.h"
+
using namespace nemiver::common;
@@ -175,6 +177,115 @@ ask_yes_no_cancel_question (const common::UString &a_message)
return dialog.run ();
}
+bool
+ask_user_to_select_file (const UString &a_file_name,
+ const UString &a_default_dir,
+ UString &a_selected_file_path)
+{
+ LocateFileDialog dialog ("", a_file_name);
+ // start looking in the default directory
+ dialog.file_location (a_default_dir);
+ int result = dialog.run ();
+ if (result == Gtk::RESPONSE_OK) {
+ UString file_path = dialog.file_location ();
+ if (!Glib::file_test (file_path, Glib::FILE_TEST_IS_REGULAR)
+ || (Glib::path_get_basename (a_file_name)
+ != Glib::path_get_basename (file_path)))
+ return false;
+ UString parent_dir =
+ Glib::filename_to_utf8 (Glib::path_get_dirname
+ (dialog.file_location ()));
+ if (!Glib::file_test (parent_dir, Glib::FILE_TEST_IS_DIR))
+ return false;
+
+ a_selected_file_path = file_path;
+ return true;
+ }
+ return false;
+}
+
+bool
+find_absolute_path_or_ask_user (const UString& a_file_path,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_session_dirs,
+ const list<UString> &a_global_dirs,
+ map<UString, bool> &a_ignore_paths,
+ bool a_ignore_if_not_found,
+ UString& a_absolute_path)
+{
+ if (!env::find_file_absolute_or_relative (a_file_path, a_prog_path,
+ a_cwd, a_session_dirs, a_global_dirs,
+ a_absolute_path)) {
+ if (a_ignore_paths.find (a_file_path)
+ != a_ignore_paths.end ())
+ // We didn't find a_file_path but as we were previously
+ // requested to *not* ask the user to locate it, just
+ // pretend we didn't find the file.
+ return false;
+ if (ask_user_to_select_file (a_file_path, a_cwd, a_absolute_path)) {
+ UString parent_dir =
+ Glib::filename_to_utf8 (Glib::path_get_dirname
+ (a_absolute_path));
+ a_session_dirs.push_back (parent_dir);
+ } else {
+ if (a_ignore_if_not_found)
+ // Don't ask the user to locate a_file_path next time.
+ a_ignore_paths[a_file_path] = true;
+ return false;
+ }
+ }
+ return true;
+}
+
+/// Given a file path P and a line number N , reads the line N from P
+/// and return it iff the function returns true. This is useful
+/// e.g. when forging a mixed source/assembly source view, and we want
+/// to display a source line N from a file P.
+///
+/// \param a_file_path the file path to consider. Not necessarily
+/// absolute. If the file is not found, it will be searched for very hard
+/// in many places.
+/// \param a_prog_path the path of to the current program. This can be
+/// useful to search for a_file_path in case we have to search for it
+/// very hard.
+/// \param a_cwd the current working directory. This can be useful to
+/// search for a_file_path.
+/// \param a_sess_dirs a list of directories where to search for if
+/// all other places we searched for failed.
+/// \param a_glob_dirs a list of directories where to seach for if
+/// anything else failed so far.
+/// \param a_ignore_paths a list of file paths to not search for. If
+/// a_file_path is present in these, we will not search for it.
+/// \param a_ignore_if_not_found if true and if we haven't found
+/// a_file_path so far, then add it to a_ignore_paths.
+/// \param a_line_number the line number to consider
+/// \param a_line the string containing the resulting line read, if
+/// and only if the function returned true.
+/// \return true upon successful completion, false otherwise.
+bool
+find_file_and_read_line (const UString &a_file_path,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_sess_dirs,
+ const list<UString> &a_glob_dirs,
+ map<UString, bool> &a_ignore_paths,
+ bool a_ignore_if_not_found,
+ int a_line_number,
+ string &a_line)
+{
+ if (a_file_path.empty ())
+ return false;
+
+ UString path;
+ if (!find_absolute_path_or_ask_user (a_file_path, a_prog_path,
+ a_cwd, a_sess_dirs, a_glob_dirs,
+ a_ignore_paths, a_ignore_if_not_found,
+ path))
+ return false;
+
+ return env::read_file_line (path, a_line_number, a_line);
+}
}//end namespace ui_utils
}//end namespace nemiver
diff --git a/src/uicommon/nmv-ui-utils.h b/src/uicommon/nmv-ui-utils.h
index 3af255b..a627cd6 100644
--- a/src/uicommon/nmv-ui-utils.h
+++ b/src/uicommon/nmv-ui-utils.h
@@ -147,6 +147,29 @@ NEMIVER_API int ask_yes_no_question (const common::UString &a_message,
NEMIVER_API int ask_yes_no_cancel_question (const common::UString &a_message);
+NEMIVER_API bool ask_user_to_select_file (const UString &a_file_name,
+ const UString &a_default_dir,
+ UString &a_selected_file_path);
+
+NEMIVER_API bool find_absolute_path_or_ask_user (const UString& a_file_path,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_sess_dirs,
+ const list<UString> &a_glob_dirs,
+ map<UString, bool> &a_ignore_paths,
+ bool a_ignore_if_not_found,
+ UString& a_absolute_path);
+
+bool find_file_and_read_line (const UString &a_file_path,
+ const UString &a_prog_path,
+ const UString &a_cwd,
+ list<UString> &a_sess_dirs,
+ const list<UString> &a_glob_dirs,
+ map<UString, bool> &a_ignore_paths,
+ bool a_ignore_if_not_found,
+ int a_line_number,
+ string &a_line);
+
template <class T>
T*
get_widget_from_glade (const Glib::RefPtr<Gnome::Glade::Xml> &a_glade,
diff --git a/tests/test-disassemble.cc b/tests/test-disassemble.cc
index 4e5ba4b..6210c24 100644
--- a/tests/test-disassemble.cc
+++ b/tests/test-disassemble.cc
@@ -29,8 +29,8 @@
#include <glibmm.h>
#include "common/nmv-initializer.h"
#include "common/nmv-safe-ptr-utils.h"
+#include "common/nmv-asm-utils.h"
#include "nmv-i-debugger.h"
-#include "nmv-asm-utils.h"
#include "nmv-dbg-common.h"
using namespace nemiver;
diff --git a/tests/test-gdbmi.cc b/tests/test-gdbmi.cc
index f78d01b..ffbcaf7 100644
--- a/tests/test-gdbmi.cc
+++ b/tests/test-gdbmi.cc
@@ -3,9 +3,9 @@
#include <map>
#include <boost/test/unit_test.hpp>
#include "dbgengine/nmv-gdbmi-parser.h"
-#include "dbgengine/nmv-asm-utils.h"
#include "common/nmv-exception.h"
#include "common/nmv-initializer.h"
+#include "common/nmv-asm-utils.h"
using namespace std;
using namespace nemiver;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]