diff options
author | Tom Tromey <tom@tromey.com> | 2018-10-09 22:21:05 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2018-12-28 12:49:54 -0700 |
commit | 62f29fda90cf1d5a1899f57ef78452471c707fd6 (patch) | |
tree | 4d2e519c41de4248f7b4f169f8f379f73f3f0a51 /gdb/tui | |
parent | 4a3045920bbe4e50a0f4920b0fdc4e88ef23015c (diff) | |
download | gdb-62f29fda90cf1d5a1899f57ef78452471c707fd6.zip gdb-62f29fda90cf1d5a1899f57ef78452471c707fd6.tar.gz gdb-62f29fda90cf1d5a1899f57ef78452471c707fd6.tar.bz2 |
Highlight source code using GNU Source Highlight
This changes gdb to highlight source using GNU Source Highlight, if it
is available.
This affects the output of the "list" command and also the TUI source
window.
No new test because I didn't see a way to make it work when Source
Highlight is not found.
gdb/ChangeLog
2018-12-28 Tom Tromey <tom@tromey.com>
* utils.h (can_emit_style_escape): Declare.
* utils.c (can_emit_style_escape): No longer static.
* cli/cli-style.c (set_style_enabled): New function.
(_initialize_cli_style): Use it.
* tui/tui-winsource.c (tui_show_source_line): Use tui_puts.
(tui_alloc_source_buffer): Change how source lines are allocated.
* tui/tui-source.c (copy_source_line): New function.
(tui_set_source_content): Use source cache.
* tui/tui-io.h (tui_puts): Update.
* tui/tui-io.c (tui_puts_internal): Add window parameter.
(tui_puts): Likewise.
(tui_redisplay_readline): Update.
* tui/tui-data.c (free_content_elements): Change how source window
contents are freed.
* source.c (forget_cached_source_info): Clear the source cache.
(print_source_lines_base): Use the source cache.
* source-cache.h: New file.
* source-cache.c: New file.
* configure.ac: Check for GNU Source Highlight library.
* configure: Update.
* config.in: Update.
* Makefile.in (SRCHIGH_LIBS, SRCHIGH_CFLAGS): New variables.
(INTERNAL_CFLAGS_BASE): Add SRCHIGH_CFLAGS.
(CLIBS): Add SRCHIGH_LIBS.
(COMMON_SFILES): Add source-cache.c.
(HFILES_NO_SRCDIR): Add source-cache.h.
Diffstat (limited to 'gdb/tui')
-rw-r--r-- | gdb/tui/tui-data.c | 5 | ||||
-rw-r--r-- | gdb/tui/tui-io.c | 11 | ||||
-rw-r--r-- | gdb/tui/tui-io.h | 4 | ||||
-rw-r--r-- | gdb/tui/tui-source.c | 302 | ||||
-rw-r--r-- | gdb/tui/tui-winsource.c | 17 |
5 files changed, 160 insertions, 179 deletions
diff --git a/gdb/tui/tui-data.c b/gdb/tui/tui-data.c index 4391f0d..2b95f19 100644 --- a/gdb/tui/tui-data.c +++ b/gdb/tui/tui-data.c @@ -838,7 +838,7 @@ free_content_elements (tui_win_content content, { int i; - if (type == SRC_WIN || type == DISASSEM_WIN) + if (type == DISASSEM_WIN) { /* Free whole source block. */ xfree (content[0]->which_element.source.line); @@ -854,6 +854,9 @@ free_content_elements (tui_win_content content, { switch (type) { + case SRC_WIN: + xfree (element->which_element.source.line); + break; case DATA_WIN: xfree (element); break; diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c index 5a84d08..29994a6 100644 --- a/gdb/tui/tui-io.c +++ b/gdb/tui/tui-io.c @@ -367,9 +367,8 @@ tui_write (const char *buf, size_t length) } static void -tui_puts_internal (const char *string, int *height) +tui_puts_internal (WINDOW *w, const char *string, int *height) { - WINDOW *w = TUI_CMD_WIN->generic.handle; char c; int prev_col = 0; @@ -410,9 +409,11 @@ tui_puts_internal (const char *string, int *height) necessary. */ void -tui_puts (const char *string) +tui_puts (const char *string, WINDOW *w) { - tui_puts_internal (string, nullptr); + if (w == nullptr) + w = TUI_CMD_WIN->generic.handle; + tui_puts_internal (w, string, nullptr); } /* Readline callback. @@ -453,7 +454,7 @@ tui_redisplay_readline (void) prev_col = 0; height = 1; if (prompt != nullptr) - tui_puts_internal (prompt, &height); + tui_puts_internal (TUI_CMD_WIN->generic.handle, prompt, &height); prev_col = getcurx (w); for (in = 0; in <= rl_end; in++) diff --git a/gdb/tui/tui-io.h b/gdb/tui/tui-io.h index 11752d0..9588763 100644 --- a/gdb/tui/tui-io.h +++ b/gdb/tui/tui-io.h @@ -22,11 +22,13 @@ #ifndef TUI_IO_H #define TUI_IO_H +#include "gdb_curses.h" + struct ui_out; class cli_ui_out; /* Print the string in the curses command window. */ -extern void tui_puts (const char *); +extern void tui_puts (const char *, WINDOW * = nullptr); /* Print LENGTH characters from the buffer pointed to by BUF to the curses command window. */ diff --git a/gdb/tui/tui-source.c b/gdb/tui/tui-source.c index 3c4f06b..260b274 100644 --- a/gdb/tui/tui-source.c +++ b/gdb/tui/tui-source.c @@ -28,14 +28,90 @@ #include "symtab.h" #include "objfiles.h" #include "filenames.h" +#include "source-cache.h" #include "tui/tui.h" #include "tui/tui-data.h" +#include "tui/tui-io.h" #include "tui/tui-stack.h" #include "tui/tui-winsource.h" #include "tui/tui-source.h" #include "gdb_curses.h" +/* A helper function for tui_set_source_content that extracts some + source text from PTR. LINE_NO is the line number; FIRST_COL is the + first column to extract, and LINE_WIDTH is the number of characters + to display. Returns a string holding the desired text. */ + +static std::string +copy_source_line (const char **ptr, int line_no, int first_col, + int line_width) +{ + const char *lineptr = *ptr; + + /* Init the line with the line number. */ + std::string result = string_printf ("%-6d", line_no); + int len = result.size (); + len = len - ((len / tui_tab_width) * tui_tab_width); + result.append (len, ' '); + + int column = 0; + char c; + do + { + int skip_bytes; + + c = *lineptr; + if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes)) + { + /* We always have to preserve escapes. */ + result.append (lineptr, lineptr + skip_bytes); + lineptr += skip_bytes; + continue; + } + + ++lineptr; + ++column; + /* We have to process all the text in order to pick up all the + escapes. */ + if (column < first_col || column > first_col + line_width) + continue; + + if (c == '\n' || c == '\r' || c == '\0') + { + /* Nothing. */ + } + else if (c < 040 && c != '\t') + { + result.push_back ('^'); + result.push_back (c + 0100); + } + else if (c == 0177) + { + result.push_back ('^'); + result.push_back ('?'); + } + else if (c == '\t') + { + int j, max_tab_len = tui_tab_width; + + for (j = column - ((column / max_tab_len) * max_tab_len); + j < max_tab_len && column < first_col + line_width; + column++, j++) + result.push_back (' '); + } + else + result.push_back (c); + } + while (c != '\0' && c != '\n' && c != '\r'); + + if (c == '\r' && *lineptr == '\n') + ++lineptr; + *ptr = lineptr; + + return result; +} + /* Function to display source in the source window. */ enum tui_status tui_set_source_content (struct symtab *s, @@ -46,8 +122,7 @@ tui_set_source_content (struct symtab *s, if (s != (struct symtab *) NULL) { - int i, c, line_width, nlines; - char *src_line = 0; + int line_width, nlines; if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS) { @@ -55,8 +130,10 @@ tui_set_source_content (struct symtab *s, /* Take hilite (window border) into account, when calculating the number of lines. */ nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no; - scoped_fd desc = open_source_file (s); - if (desc.get () < 0) + + std::string srclines; + if (!g_source_cache.get_source_lines (s, line_no, line_no + nlines, + &srclines)) { if (!noerror) { @@ -70,165 +147,68 @@ tui_set_source_content (struct symtab *s, } else { - if (s->line_charpos == 0) - find_source_lines (s, desc.get ()); - - if (line_no < 1 || line_no > s->nlines) - printf_unfiltered ("Line number %d out of range; " - "%s has %d lines.\n", - line_no, - symtab_to_filename_for_display (s), - s->nlines); - else if (lseek (desc.get (), s->line_charpos[line_no - 1], 0) - < 0) - perror_with_name (symtab_to_filename_for_display (s)); - else + int cur_line_no, cur_line; + struct tui_gen_win_info *locator + = tui_locator_win_info_ptr (); + struct tui_source_info *src + = &TUI_SRC_WIN->detail.source_info; + const char *s_filename = symtab_to_filename_for_display (s); + + if (TUI_SRC_WIN->generic.title) + xfree (TUI_SRC_WIN->generic.title); + TUI_SRC_WIN->generic.title = xstrdup (s_filename); + + xfree (src->fullname); + src->fullname = xstrdup (symtab_to_fullname (s)); + + cur_line = 0; + src->gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s)); + src->start_line_or_addr.loa = LOA_LINE; + cur_line_no = src->start_line_or_addr.u.line_no = line_no; + + const char *iter = srclines.c_str (); + while (cur_line < nlines) { - int offset, cur_line_no, cur_line, cur_len, threshold; - struct tui_gen_win_info *locator - = tui_locator_win_info_ptr (); - struct tui_source_info *src - = &TUI_SRC_WIN->detail.source_info; - const char *s_filename = symtab_to_filename_for_display (s); - - if (TUI_SRC_WIN->generic.title) - xfree (TUI_SRC_WIN->generic.title); - TUI_SRC_WIN->generic.title = xstrdup (s_filename); - - xfree (src->fullname); - src->fullname = xstrdup (symtab_to_fullname (s)); - - /* Determine the threshold for the length of the - line and the offset to start the display. */ - offset = src->horizontal_offset; - threshold = (line_width - 1) + offset; - gdb_file_up stream = desc.to_file (FOPEN_RT); - clearerr (stream.get ()); - cur_line = 0; - src->gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s)); - src->start_line_or_addr.loa = LOA_LINE; - cur_line_no = src->start_line_or_addr.u.line_no = line_no; - if (offset > 0) - src_line = (char *) xmalloc ( - (threshold + 1) * sizeof (char)); - while (cur_line < nlines) - { - struct tui_win_element *element - = TUI_SRC_WIN->generic.content[cur_line]; - - /* Get the first character in the line. */ - c = fgetc (stream.get ()); - - if (offset == 0) - src_line = TUI_SRC_WIN->generic.content[cur_line] - ->which_element.source.line; - /* Init the line with the line number. */ - sprintf (src_line, "%-6d", cur_line_no); - cur_len = strlen (src_line); - i = cur_len - ((cur_len / tui_tab_width) - * tui_tab_width); - while (i < tui_tab_width) - { - src_line[cur_len] = ' '; - i++; - cur_len++; - } - src_line[cur_len] = (char) 0; - - /* Set whether element is the execution point - and whether there is a break point on it. */ - element->which_element.source.line_or_addr.loa = - LOA_LINE; - element->which_element.source.line_or_addr.u.line_no = - cur_line_no; - element->which_element.source.is_exec_point = - (filename_cmp (locator->content[0] - ->which_element.locator.full_name, - symtab_to_fullname (s)) == 0 - && cur_line_no - == locator->content[0] - ->which_element.locator.line_no); - if (c != EOF) - { - i = strlen (src_line) - 1; - do - { - if ((c != '\n') && (c != '\r') - && (++i < threshold)) - { - if (c < 040 && c != '\t') - { - src_line[i++] = '^'; - src_line[i] = c + 0100; - } - else if (c == 0177) - { - src_line[i++] = '^'; - src_line[i] = '?'; - } - else - { /* Store the charcter in the - line buffer. If it is a tab, - then translate to the correct - number of chars so we don't - overwrite our buffer. */ - if (c == '\t') - { - int j, max_tab_len - = tui_tab_width; - - for (j = i - ((i / max_tab_len) - * max_tab_len); - j < max_tab_len - && i < threshold; - i++, j++) - src_line[i] = ' '; - i--; - } - else - src_line[i] = c; - } - src_line[i + 1] = 0; - } - else - { /* If we have not reached EOL, then - eat chars until we do. */ - while (c != EOF && c != '\n' && c != '\r') - c = fgetc (stream.get ()); - /* Handle non-'\n' end-of-line. */ - if (c == '\r' - && (c = fgetc (stream.get ())) != '\n' - && c != EOF) - { - ungetc (c, stream.get ()); - c = '\r'; - } - - } - } - while (c != EOF && c != '\n' && c != '\r' - && i < threshold - && (c = fgetc (stream.get ()))); - } - /* Now copy the line taking the offset into - account. */ - if (offset == 0) - ; - else if (strlen (src_line) > offset) - strcpy (TUI_SRC_WIN->generic.content[cur_line] - ->which_element.source.line, - &src_line[offset]); - else - TUI_SRC_WIN->generic.content[cur_line] - ->which_element.source.line[0] = (char) 0; - cur_line++; - cur_line_no++; - } - if (offset > 0) - xfree (src_line); - TUI_SRC_WIN->generic.content_size = nlines; - ret = TUI_SUCCESS; + struct tui_win_element *element + = TUI_SRC_WIN->generic.content[cur_line]; + + std::string text; + if (*iter != '\0') + text = copy_source_line (&iter, cur_line_no, + src->horizontal_offset, + line_width); + + /* Set whether element is the execution point + and whether there is a break point on it. */ + element->which_element.source.line_or_addr.loa = + LOA_LINE; + element->which_element.source.line_or_addr.u.line_no = + cur_line_no; + element->which_element.source.is_exec_point = + (filename_cmp (locator->content[0] + ->which_element.locator.full_name, + symtab_to_fullname (s)) == 0 + && cur_line_no + == locator->content[0] + ->which_element.locator.line_no); + + xfree (TUI_SRC_WIN->generic.content[cur_line] + ->which_element.source.line); + int alloc_len = text.size (); + if (alloc_len < line_width) + alloc_len = line_width + 1; + TUI_SRC_WIN->generic.content[cur_line] + ->which_element.source.line + = (char *) xmalloc (alloc_len); + strcpy (TUI_SRC_WIN->generic.content[cur_line] + ->which_element.source.line, + text.c_str ()); + + cur_line++; + cur_line_no++; } + TUI_SRC_WIN->generic.content_size = nlines; + ret = TUI_SUCCESS; } } } diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c index 0bf7438..00b4b9e 100644 --- a/gdb/tui/tui-winsource.c +++ b/gdb/tui/tui-winsource.c @@ -31,6 +31,7 @@ #include "tui/tui.h" #include "tui/tui-data.h" +#include "tui/tui-io.h" #include "tui/tui-stack.h" #include "tui/tui-win.h" #include "tui/tui-wingeneral.h" @@ -277,8 +278,9 @@ tui_show_source_line (struct tui_win_info *win_info, int lineno) if (line->which_element.source.is_exec_point) wattron (win_info->generic.handle, A_STANDOUT); - mvwaddstr (win_info->generic.handle, lineno, 1, - line->which_element.source.line); + wmove (win_info->generic.handle, lineno, 1); + tui_puts (line->which_element.source.line, + win_info->generic.handle); if (line->which_element.source.is_exec_point) wattroff (win_info->generic.handle, A_STANDOUT); @@ -595,7 +597,6 @@ tui_update_exec_info (struct tui_win_info *win_info) enum tui_status tui_alloc_source_buffer (struct tui_win_info *win_info) { - char *src_line_buf; int i, line_width, max_lines; /* The window width/height includes the highlight box. Determine actual @@ -603,20 +604,14 @@ tui_alloc_source_buffer (struct tui_win_info *win_info) max_lines = win_info->generic.height - 2; line_width = win_info->generic.width - 2 + 1; - /* - * Allocate the buffer for the source lines. Do this only once - * since they will be re-used for all source displays. The only - * other time this will be done is when a window's size changes. - */ + /* Allocate the buffer for the source lines. */ if (win_info->generic.content == NULL) { - src_line_buf = (char *) - xmalloc ((max_lines * line_width) * sizeof (char)); /* Allocate the content list. */ win_info->generic.content = tui_alloc_content (max_lines, SRC_WIN); for (i = 0; i < max_lines; i++) win_info->generic.content[i]->which_element.source.line - = src_line_buf + (line_width * i); + = (char *) xmalloc (line_width); } return TUI_SUCCESS; |