This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Automatic wrapping prototype


This is just something I hacked up tonight, since (A) I said I would try it
someday, and (B) Paolo Bonzini sent me a miraculously useful pointer to
gnulib's line wrapping code.  It includes a very clever, multibyte and
unicode aware, standards-compliant function that does all the heavy lifting
that I would have trouble coming up with myself.

To try this patch yourself, if you want to:

1.  Install gnulib; I'm using Debian's prepackaged version.  Gnulib
is a collection of standard GNU contributed utilities, designed to
be automatically imported into other packages.

2.  Apply the patch.

3.  In the gdb directory, run:

gnulib-tool --import --source-base=lib --doc-base=doc --tests-base=tests
  --lib=libgnu --macro-prefix=gl --m4-base=m4 linebreak

to create lib and m4 subdirectories.

4.  Regenerate aclocal.m4 - you have to run "aclocal -I m4" now instead of
just aclocal.

5.  Regenerate configure.

6.  Build GDB.

7.  "set width" to various small things and type undefined commands.
Watch the error message wrap!

I'm not proposing to include this as-is.  I didn't work out all the
interactions with e.g. when things get translated by gettext (and when
they don't), whether output is going to the screen or somewhere else,
the existing wrap_here mechanism, and support for indenting wrapped
lines.

I haven't thought about the hard parts yet, but it seems to me that it would
be reasonable to completely rip out wrap_here mechanism and let this do it.
I don't think the hints we're currently supplying are valuable given an
algorithm sufficiently good at avoiding breaking words.  The case where
using wrap_here could be superior is user-supplied identifiers (like
C++ symbol names) which the algorithm might decide to wrap; this code
isn't context sensitive in that regard.  If we think that's really
important to preserve, you can pass overrides to the line wrapping
routine in gnulib telling it to consider certain bits unwrappable,
or we could combine this code with the existing wrapping mechanism.

For instance c-typeprint.c tries to wrap between function arguments
instead of between the argument and its type.  

Just an FYI for now; I'll play with this again sometime.

-- 
Daniel Jacobowitz
CodeSourcery

? lib
? m4
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.844
diff -u -p -r1.844 Makefile.in
--- Makefile.in	21 Sep 2006 14:00:53 -0000	1.844
+++ Makefile.in	1 Oct 2006 03:19:32 -0000
@@ -150,6 +150,10 @@ LIBICONV = @LIBICONV@
 TARGET_SYSTEM_ROOT = @TARGET_SYSTEM_ROOT@
 TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@
 
+# Helper code from gnulib.
+LIBGNU = lib/libgnu.a
+INCGNU = -I$(srcdir)/lib -Ilib
+
 #
 # CLI sub directory definitons
 #
@@ -354,7 +358,7 @@ CXXFLAGS = -g -O
 INTERNAL_CFLAGS_BASE = \
 	$(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
 	$(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \
-	$(BFD_CFLAGS) $(INCLUDE_CFLAGS) \
+	$(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(INCGNU) \
 	$(INTL_CFLAGS) $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS)
 INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS)
 INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS)
@@ -379,13 +383,13 @@ INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CF
 # you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS='
 INSTALLED_LIBS=-lbfd -lreadline -lopcodes -liberty \
 	$(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
-	-lintl -liberty
+	-lintl -liberty $(LIBGNU)
 CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) \
 	$(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
 	$(LIBICONV) $(LIBEXPAT) \
-	$(LIBIBERTY) $(WIN32LIBS)
+	$(LIBIBERTY) $(WIN32LIBS) $(LIBGNU)
 CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \
-	$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS)
+	$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU)
 
 ADD_FILES = $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
 ADD_DEPS = $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
@@ -635,6 +639,12 @@ tm_h =		@tm_h@
 nm_h =		@nm_h@
 
 #
+# gdb/lib/ headers
+#
+
+linebreak_h = lib/linebreak.h
+
+#
 # gdb/ headers
 #
 
@@ -995,7 +1005,10 @@ DISTSTUFF = $(YYFILES)
 	$(CC) -c $(INTERNAL_CFLAGS) $<
 
 all: gdb$(EXEEXT) $(CONFIG_ALL)
-	@$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do
+	@$(MAKE) $(FLAGS_TO_PASS) DO=all \
+	  "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//' | sed 's/lib//'`" \
+	  subdir_do
+
 .PHONY: all-tui
 all-tui: $(TUI)$(EXEEXT)
 
@@ -1221,6 +1234,12 @@ $(TUI)$(EXEEXT): tui-main.o libgdb.a $(A
 		-o $(TUI)$(EXEEXT) tui-main.o libgdb.a \
 		$(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES)
 
+# Convenience rule to handle recursion.
+$(LIBGNU): all-lib
+all-lib:
+	@$(MAKE) $(FLAGS_TO_PASS) DO=all DODIRS=lib subdir_do
+.PHONY: all-lib
+
 # Create a library of the gdb object files and build GDB by linking
 # against that.
 #
@@ -2795,7 +2814,7 @@ utils.o: utils.c $(defs_h) $(gdb_assert_
 	$(exceptions_h) $(tui_h) $(gdbcmd_h) $(serial_h) $(bfd_h) \
 	$(target_h) $(demangle_h) $(expression_h) $(language_h) $(charset_h) \
 	$(annotate_h) $(filenames_h) $(symfile_h) $(inferior_h) $(top_h) \
-	$(gdb_curses_h) $(readline_h) $(gdb_obstack_h)
+	$(gdb_curses_h) $(readline_h) $(gdb_obstack_h) $(linebreak_h)
 uw-thread.o: uw-thread.c $(defs_h) $(gdbthread_h) $(target_h) $(inferior_h) \
 	$(regcache_h) $(gregset_h)
 v850-tdep.o: v850-tdep.c $(defs_h) $(frame_h) $(frame_base_h) $(trad_frame_h) \
Index: configure.ac
===================================================================
RCS file: /cvs/src/src/gdb/configure.ac,v
retrieving revision 1.34
diff -u -p -r1.34 configure.ac
--- configure.ac	8 Aug 2006 20:26:23 -0000	1.34
+++ configure.ac	1 Oct 2006 03:19:34 -0000
@@ -28,12 +28,13 @@ AC_CONFIG_HEADER(config.h:config.in)
 AM_MAINTAINER_MODE
 
 AC_PROG_CC
+gl_EARLY
 AC_GNU_SOURCE
 AC_AIX
 AC_ISC_POSIX
 AM_PROG_CC_STDC
 
-AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/..)
+AC_CONFIG_AUX_DIR(..)
 AC_CANONICAL_SYSTEM
 
 dnl List of object files and targets accumulated by configure.
@@ -61,10 +62,14 @@ if test x"$USE_NLS" = xyes; then
    CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-po"
 fi
 
+gl_INIT
+
 PACKAGE=gdb
 AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package. ])
 AC_SUBST(PACKAGE)
 
+AM_INIT_AUTOMAKE(gdb, VERSION)
+
 debugdir=${libdir}/debug
 	 
 AC_ARG_WITH(separate-debug-dir,
@@ -75,7 +80,7 @@ AC_DEFINE_DIR(DEBUGDIR, debugdir,
               [Global directory for separate debug files. ])
 #AC_DEFINE_UNQUOTED(DEBUGDIR, "$debugdir"),
 
-AC_CONFIG_SUBDIRS(doc testsuite)
+AC_CONFIG_SUBDIRS(doc testsuite lib)
 
 # Provide defaults for some variables set by the per-host and per-target
 # configuration.
@@ -101,8 +106,6 @@ if test "x$targ_defvec" != x; then
     [Define to BFD's default target vector. ])
 fi
 
-AC_ARG_PROGRAM
-
 # The CLI cannot be disabled yet, but may be in the future.
 
 # Enable CLI.
@@ -1552,7 +1555,7 @@ AC_DEFINE(GDB_DEFAULT_HOST_CHARSET, "ISO
 
 AM_ICONV
 
-AC_OUTPUT(Makefile .gdbinit:gdbinit.in,
+AC_OUTPUT(Makefile .gdbinit:gdbinit.in lib/Makefile,
 [
 dnl Autoconf doesn't provide a mechanism for modifying definitions 
 dnl provided by makefile fragments.
Index: exceptions.c
===================================================================
RCS file: /cvs/src/src/gdb/exceptions.c,v
retrieving revision 1.24
diff -u -p -r1.24 exceptions.c
--- exceptions.c	3 Feb 2006 21:50:25 -0000	1.24
+++ exceptions.c	1 Oct 2006 03:19:34 -0000
@@ -298,7 +298,12 @@ print_exception (struct ui_file *file, s
      as that way the MI's behavior is preserved.  */
   const char *start;
   const char *end;
-  for (start = e.message; start != NULL; start = end)
+  char *message;
+  extern char *wrap_message (const char *);
+
+  message = wrap_message (e.message);
+
+  for (start = message; start != NULL; start = end)
     {
       end = strchr (start, '\n');
       if (end == NULL)
@@ -310,6 +315,7 @@ print_exception (struct ui_file *file, s
 	}
     }					    
   fprintf_filtered (file, "\n");
+  xfree (message);
 
   /* Now append the annotation.  */
   switch (e.reason)
Index: utils.c
===================================================================
RCS file: /cvs/src/src/gdb/utils.c,v
retrieving revision 1.169
diff -u -p -r1.169 utils.c
--- utils.c	21 Sep 2006 13:50:51 -0000	1.169
+++ utils.c	1 Oct 2006 03:19:35 -0000
@@ -27,6 +27,7 @@
 #include "gdb_string.h"
 #include "event-top.h"
 #include "exceptions.h"
+#include "linebreak.h"
 
 #ifdef TUI
 #include "tui/tui.h"		/* For tui_get_command_dimension.   */
@@ -2304,6 +2305,45 @@ print_spaces_filtered (int n, struct ui_
   fputs_filtered (n_spaces (n), stream);
 }
 
+/* Automatic word wrapping (as opposed to the manual kind using
+   wrap_here).  The return value is an xmalloced copy of MESSAGE,
+   with interior newlines inserted for wrapping.  This should be
+   called on the result of gettext.  */
+
+char *
+wrap_message (const char *message)
+{
+  size_t length = strlen (message);
+  size_t i, n_breaks;
+  char *breaks, *result, *p;
+
+  if (chars_per_line == UINT_MAX)
+    return xstrdup (message);
+
+  /* Note to self: the NULL is "o", overrides.  We could use this
+     to even use this routine for bits we don't want to wrap
+     during.  */
+  breaks = xmalloc (length);
+  mbs_width_linebreaks (message, length, chars_per_line, wrap_column, 0,
+			NULL, locale_charset (), breaks);
+
+  for (n_breaks = 0, i = 0; i < length; i++)
+    if (breaks[i] == UC_BREAK_POSSIBLE)
+      n_breaks++;
+
+  result = xmalloc (length + n_breaks + 1);
+  for (p = result, i = 0; i < length; i++)
+    {
+      if (breaks[i] == UC_BREAK_POSSIBLE)
+	*p++ = '\n';
+      *p++ = message[i];
+    }
+  *p = '\0';
+
+  return result;
+}
+
+
 /* C++/ObjC demangler stuff.  */
 
 /* fprintf_symbol_filtered attempts to demangle NAME, a symbol in language


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]