Fix tui compilation with Solaris libcurses (PR tui/21482)

Message ID yddh90i1r31.fsf@CeBiTec.Uni-Bielefeld.DE
State New, archived
Headers

Commit Message

Rainer Orth May 18, 2017, 8:56 a.m. UTC
  On both mainline and the 8.0 branch, gdb compilation fails on Solaris 10
with the native libcurses:

* Initially, compilation failed like this:

In file included from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/gdb_curses.h:42:
0,
                 from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-data.h:2
6,
                 from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-disasm.c
:31:
/vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-disasm.c: In function ‘CORE_A
DDR tui_disassemble(gdbarch*, tui_asm_line*, CORE_ADDR, int)’:
/vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-disasm.c:71:19: error: ‘class
 string_file’ has no member named ‘wclear’; did you mean ‘clear’?
       gdb_dis_out.clear ();
                   ^
/vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-disasm.c:78:19: error: ‘class
 string_file’ has no member named ‘wclear’; did you mean ‘clear’?
       gdb_dis_out.clear ();
                   ^
make[2]: *** [Makefile:1927: tui-disasm.o] Error 1

  It turned out this happens because <curses.h> has

#define clear()         wclear(stdscr)

  This can be avoided by defining NOMACROS, which the patch below does
  for solaris2.*.

* Even with this workaround, compilation fails in gdb/tui for several
  instances of the same problem:

/vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c: In function ‘void tui_erase_source_content(tui_win_info*, int)’:
/vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c:257:18: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
        no_src_str);
                  ^
In file included from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/gdb_curses.h:42:0,
                 from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-data.h:26,
                 from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c:33:
/vol/gcc-7/lib/gcc/sparc-sun-solaris2.10/7.1.0/include-fixed/curses.h:699:12: note:   initializing argument 4 of ‘int mvwaddstr(WINDOW*, int, int, char*)’
 extern int mvwaddstr(WINDOW *, int, int, char *);
            ^~~~~~~~~
make[2]: *** [Makefile:1927: tui-winsource.o] Error 1

  Unlike ncurses, <curses.h> declares 

extern int mvwaddstr(WINDOW *, int, int, char *);

  i.e. the last arg is char *, not const char *.

  The patch fixes this by casting the last arg to mvwaddstr to char *,
  as was recently done on mainline in a newterm() call (the only
  difference between 8.0 and mainline gdb/tui).

With those changes, gdb on the 8.0 branch compiles cleanly on
sparcv9-sun-solaris2.10 with native curses and amd64-pc-solaris2.12
with bundled ncurses (well, almost: on Solaris 12 ncurses in
/usr/include is used, but gdb linked against -lcurses which fails:

Undefined                       first referenced
 symbol                             in file
wattr_on                            tui-wingeneral.o
wattr_off                           tui-wingeneral.o

but that's a different and preexisting problem).

Ok for mainline and 8.0 branch?

	Rainer
  

Comments

Pedro Alves May 18, 2017, 1:19 p.m. UTC | #1
On 05/18/2017 09:56 AM, Rainer Orth wrote:
> On both mainline and the 8.0 branch, gdb compilation fails on Solaris 10
> with the native libcurses:
> 
> * Initially, compilation failed like this:
> 
> In file included from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/gdb_curses.h:42:
> 0,
>                  from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-data.h:2
> 6,
>                  from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-disasm.c
> :31:
> /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-disasm.c: In function ‘CORE_A
> DDR tui_disassemble(gdbarch*, tui_asm_line*, CORE_ADDR, int)’:
> /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-disasm.c:71:19: error: ‘class
>  string_file’ has no member named ‘wclear’; did you mean ‘clear’?
>        gdb_dis_out.clear ();
>                    ^
> /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-disasm.c:78:19: error: ‘class
>  string_file’ has no member named ‘wclear’; did you mean ‘clear’?
>        gdb_dis_out.clear ();
>                    ^
> make[2]: *** [Makefile:1927: tui-disasm.o] Error 1
> 
>   It turned out this happens because <curses.h> has
> 
> #define clear()         wclear(stdscr)
> 
>   This can be avoided by defining NOMACROS, which the patch below does
>   for solaris2.*.

We already handle some curses warts in gdb_curses.h (and then
include that header instead everywhere).  I think this could go there,
even unconditionally.  (This is more about curses implementation
than OS strictly speaking.  Googling around finds hits for that
macro in the AIX curses.h header, for example.).  Looks like ncurses
checks NCURSES_NOMACROS instead of NOMACROS, we could define that too.

> 
> * Even with this workaround, compilation fails in gdb/tui for several
>   instances of the same problem:
> 
> /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c: In function ‘void tui_erase_source_content(tui_win_info*, int)’:
> /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c:257:18: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
>         no_src_str);
>                   ^
> In file included from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/gdb_curses.h:42:0,
>                  from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-data.h:26,
>                  from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c:33:
> /vol/gcc-7/lib/gcc/sparc-sun-solaris2.10/7.1.0/include-fixed/curses.h:699:12: note:   initializing argument 4 of ‘int mvwaddstr(WINDOW*, int, int, char*)’
>  extern int mvwaddstr(WINDOW *, int, int, char *);
>             ^~~~~~~~~
> make[2]: *** [Makefile:1927: tui-winsource.o] Error 1
> 
>   Unlike ncurses, <curses.h> declares 
> 
> extern int mvwaddstr(WINDOW *, int, int, char *);
> 
>   i.e. the last arg is char *, not const char *.
> 
>   The patch fixes this by casting the last arg to mvwaddstr to char *,
>   as was recently done on mainline in a newterm() call (the only
>   difference between 8.0 and mainline gdb/tui).

That's fine with me.

Looking at:

 https://docs.oracle.com/cd/E19455-01/806-0629/6j9vjco9i/index.html

I see that this affects several APIs, so nicer would be to
fix this centrally in gdb_curses.h like we fix e.g.,
PyObject_GetAttrString in python/python-internal.h.  But that can
be for another day.

> 
> With those changes, gdb on the 8.0 branch compiles cleanly on
> sparcv9-sun-solaris2.10 with native curses and amd64-pc-solaris2.12
> with bundled ncurses (well, almost: on Solaris 12 ncurses in
> /usr/include is used, but gdb linked against -lcurses which fails:
> 
> Undefined                       first referenced
>  symbol                             in file
> wattr_on                            tui-wingeneral.o
> wattr_off                           tui-wingeneral.o
> 
> but that's a different and preexisting problem).

These two problems would be better pushed as two separate patches
(with the rationales given above as separate commit logs).

> Ok for mainline and 8.0 branch?

The cast bits are OK.  I'd like to hear your opinion on
moving the NOMACROS define to gdb_curses.h, before including
<curses.h>.

Thanks,
Pedro Alves
  
Rainer Orth May 18, 2017, 1:36 p.m. UTC | #2
Hi Pedro,

>>   It turned out this happens because <curses.h> has
>> 
>> #define clear()         wclear(stdscr)
>> 
>>   This can be avoided by defining NOMACROS, which the patch below does
>>   for solaris2.*.
>
> We already handle some curses warts in gdb_curses.h (and then
> include that header instead everywhere).  I think this could go there,
> even unconditionally.  (This is more about curses implementation
> than OS strictly speaking.  Googling around finds hits for that
> macro in the AIX curses.h header, for example.).  Looks like ncurses

probably of SysVr4 origin ultimately: at least I already found it in
those sources.

> checks NCURSES_NOMACROS instead of NOMACROS, we could define that too.

Makes sense (unless this creates problems of its own ;-).

>> * Even with this workaround, compilation fails in gdb/tui for several
>>   instances of the same problem:
>> 
>> /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c: In function ‘void tui_erase_source_content(tui_win_info*, int)’:
>> /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c:257:18: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
>>         no_src_str);
>>                   ^
>> In file included from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/gdb_curses.h:42:0,
>>                  from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-data.h:26,
>>                  from /vol/src/gnu/gdb/gdb-8.0-branch/local/gdb/tui/tui-winsource.c:33:
>> /vol/gcc-7/lib/gcc/sparc-sun-solaris2.10/7.1.0/include-fixed/curses.h:699:12: note:   initializing argument 4 of ‘int mvwaddstr(WINDOW*, int, int, char*)’
>>  extern int mvwaddstr(WINDOW *, int, int, char *);
>>             ^~~~~~~~~
>> make[2]: *** [Makefile:1927: tui-winsource.o] Error 1
>> 
>>   Unlike ncurses, <curses.h> declares 
>> 
>> extern int mvwaddstr(WINDOW *, int, int, char *);
>> 
>>   i.e. the last arg is char *, not const char *.
>> 
>>   The patch fixes this by casting the last arg to mvwaddstr to char *,
>>   as was recently done on mainline in a newterm() call (the only
>>   difference between 8.0 and mainline gdb/tui).
>
> That's fine with me.
>
> Looking at:
>
>  https://docs.oracle.com/cd/E19455-01/806-0629/6j9vjco9i/index.html
>
> I see that this affects several APIs, so nicer would be to
> fix this centrally in gdb_curses.h like we fix e.g.,
> PyObject_GetAttrString in python/python-internal.h.  But that can
> be for another day.

This way you centralize the knowledge why you are doing this in once
header rather than several calls/casts.  I guess we'll cross that bridge
once another function causes similar trouble.

>> With those changes, gdb on the 8.0 branch compiles cleanly on
>> sparcv9-sun-solaris2.10 with native curses and amd64-pc-solaris2.12
>> with bundled ncurses (well, almost: on Solaris 12 ncurses in
>> /usr/include is used, but gdb linked against -lcurses which fails:
>> 
>> Undefined                       first referenced
>>  symbol                             in file
>> wattr_on                            tui-wingeneral.o
>> wattr_off                           tui-wingeneral.o
>> 
>> but that's a different and preexisting problem).
>
> These two problems would be better pushed as two separate patches
> (with the rationales given above as separate commit logs).

Fine with me.  I'll look at the ncurses header vs. libcurses issue
later: so far I've just been lazy and manually linked gdb if I hit it.

>> Ok for mainline and 8.0 branch?
>
> The cast bits are OK.  I'd like to hear your opinion on
> moving the NOMACROS define to gdb_curses.h, before including
> <curses.h>.

The move makes sense to me: I just wasn't aware of that file.  I'll
prepare a separate patch.

Thanks.
        Rainer
  

Patch

# HG changeset patch
# Parent  bfb43bbf7ca9808a9e660c111b68eef77999e76c
Fix tui compilation with Solaris libcurses (PR tui/21482)

diff --git a/gdb/configure.ac b/gdb/configure.ac
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1312,6 +1312,14 @@  case $host_os in
    Solaris 2.[789] when using GCC. ])
     fi ;;
 esac
+# On Solaris, we need to define NOMACROS so the native <curses.h> doesn't
+# define clear which interferes with the clear member of class string_file.
+case $host_os in
+  solaris2.*)
+    AC_DEFINE(NOMACROS, 1,
+      [Define to 1 to avoid <curses.h> defining clear which interferes with class string_file. ])
+    ;;
+esac
 AC_CHECK_HEADERS(curses.h cursesX.h ncurses.h ncurses/ncurses.h ncurses/term.h)
 AC_CHECK_HEADERS(term.h, [], [],
 [#if HAVE_CURSES_H
diff --git a/gdb/tui/tui-windata.c b/gdb/tui/tui-windata.c
--- a/gdb/tui/tui-windata.c
+++ b/gdb/tui/tui-windata.c
@@ -117,7 +117,7 @@  tui_erase_data_content (const char *prom
       mvwaddstr (TUI_DATA_WIN->generic.handle,
 		 (TUI_DATA_WIN->generic.height / 2),
 		 x_pos,
-		 prompt);
+		 (char *) prompt);
     }
   wrefresh (TUI_DATA_WIN->generic.handle);
 }
diff --git a/gdb/tui/tui-wingeneral.c b/gdb/tui/tui-wingeneral.c
--- a/gdb/tui/tui-wingeneral.c
+++ b/gdb/tui/tui-wingeneral.c
@@ -101,7 +101,7 @@  box_win (struct tui_gen_win_info *win_in
       box (win, tui_border_vline, tui_border_hline);
 #endif
       if (win_info->title)
-        mvwaddstr (win, 0, 3, win_info->title);
+        mvwaddstr (win, 0, 3, (char *) win_info->title);
       wattroff (win, attrs);
     }
 }
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -254,7 +254,7 @@  tui_erase_source_content (struct tui_win
 	  mvwaddstr (win_info->generic.handle,
 		     (win_info->generic.height / 2),
 		     x_pos,
-		     no_src_str);
+		     (char *) no_src_str);
 
 	  /* elz: Added this function call to set the real contents of
 	     the window to what is on the screen, so that later calls
@@ -280,7 +280,7 @@  tui_show_source_line (struct tui_win_inf
     wattron (win_info->generic.handle, A_STANDOUT);
 
   mvwaddstr (win_info->generic.handle, lineno, 1,
-             line->which_element.source.line);
+             (char *) line->which_element.source.line);
   if (line->which_element.source.is_exec_point)
     wattroff (win_info->generic.handle, A_STANDOUT);
 
@@ -565,7 +565,8 @@  tui_show_exec_info_content (struct tui_w
     mvwaddstr (exec_info->handle,
 	       cur_line,
 	       0,
-	       exec_info->content[cur_line - 1]->which_element.simple_string);
+	       (char *) exec_info->content[cur_line - 1]
+			  ->which_element.simple_string);
   tui_refresh_win (exec_info);
   exec_info->content_in_use = TRUE;
 }