diff src/print.c @ 1346:01c57eb70ae9

[xemacs-hg @ 2003-03-09 02:27:27 by ben] To: xemacs-patches@xemacs.org i.c: Sleep between calls to check for I/O, since these calls are non-blocking. behavior.el: Allow other keywords for forward compatibility. cl-macs.el: Rewrite to eliminate byte-compiler warning when `return' is used without `finally'. cmdloop.el: Avoid truncated error messages for `end-of-file' and the like. cmdloop.el: Avoid char-int error after syncing. files.el: Eliminate byte-compile warnings. printer.el: Fix line-width calculations. #### This used to work. Someone's changes (perhaps by Michael Sperber?) seem to have messed something up. simple.el: Use new clear-left-side functions to avoid messages ending up on the same line as other output. xemacs.mak: Add override for info/ as well when separate source/build dirs. xemacs.mak: Order sections in main build process and add comments. Add additional dependencies to try and prevent later steps from happening when failures in earlier steps have occurred. Makefile.in.in: Order sections in main build process and add comments. Add additional dependencies to try and prevent later steps from happening when failures in earlier steps have occurred. alloc.c: Don't arbitrarily clear Vconfigure_info_directory since it messes up separate build/source dirs. console.c, console.h, device-msw.c, device.c: Add accidentally omitted msprinter console and data descriptions. print.c, console-msw.c: Add clear-left-side functionality to help keep stdio/stderr output from separate sources on separate lines. Generalize the different kinds of debugging output. Add dpa(). profile.c: Add better docs on Unix/Windows differences. regex.c: Fix problems with rel-alloc compilation caused by previous patch. emacs.c: Seg fault rather than abort on Cygwin, since gdb doesn't trap aborts properly. console-gtk-impl.h, console-gtk.h, console-msw.h, console-x-impl.h, console-x.h, dialog-gtk.c, dialog-x.c, event-msw.c, frame-gtk.c, frame-x.c, frameslots.h, glyphs-gtk.c, glyphs-x.c, gui-gtk.c, gui-x.c, inline.c, menubar-gtk.c, menubar-msw.c, menubar-x.c, scrollbar-gtk.c, scrollbar-x.c, ui-gtk.c: Delete popup-data object. Delete menubar_data field from frames, since its usage is frame-specific. Delete menubar-msw.h, gui-x.h, gui-gtk.h. Clean up handling of lwlib callback data GCPRO'ing and add missing GCPRO recomputation in widget code.
author ben
date Sun, 09 Mar 2003 02:27:46 +0000
parents 465bd3c7d932
children 59e1bbea04fe
line wrap: on
line diff
--- a/src/print.c	Sat Mar 08 22:52:26 2003 +0000
+++ b/src/print.c	Sun Mar 09 02:27:46 2003 +0000
@@ -116,19 +116,20 @@
 
 FILE *termscript;	/* Stdio stream being used for copy of all output.  */
 
-static void write_string_to_alternate_debugging_output (Ibyte *str,
+static void write_string_to_alternate_debugging_output (const Ibyte *str,
 							Bytecount len);
 
 
 
 int stdout_needs_newline;
+int stdout_clear_before_next_output;
 
 /* Basic function to actually write to a stdio stream or TTY console. */
 
 static void
-write_string_to_stdio_stream (FILE *stream, struct console *con,
-			      const Ibyte *ptr, Bytecount len,
-			      int must_flush)
+write_string_to_stdio_stream_1 (FILE *stream, struct console *con,
+				const Ibyte *ptr, Bytecount len,
+				int must_flush)
 {
   Extbyte *extptr = 0;
   Bytecount extlen = 0;
@@ -187,15 +188,74 @@
 	  retry_fwrite (extptr, 1, extlen, termscript);
 	  fflush (termscript);
 	}
-      stdout_needs_newline = (ptr[extlen - 1] != '\n');
+      stdout_needs_newline = (ptr[len - 1] != '\n');
     }
 }
 
-/* #### The following function should be replaced a call to the
-   emacs_vsprintf_*() functions.  This is the only way to ensure that
-   I18N3 works properly (many implementations of the *printf()
-   functions, including the ones included in glibc, do not implement
-   the %###$ argument-positioning syntax).
+/* Write to a stdio stream or TTY console, first clearing the left side
+   if necessary. */
+
+static void
+write_string_to_stdio_stream (FILE *stream, struct console *con,
+			      const Ibyte *ptr, Bytecount len,
+			      int must_flush)
+{
+  if (stdout_clear_before_next_output &&
+      (stream ? stream == stdout || stream == stderr :
+       CONSOLE_TTY_DATA (con)->is_stdio))
+    {
+      if (stdout_needs_newline)
+	write_string_to_stdio_stream_1 (stream, con, (Ibyte *) "\n", 1,
+					must_flush);
+      stdout_clear_before_next_output = 0;
+    }
+
+  write_string_to_stdio_stream_1 (stream, con, ptr, len, must_flush);
+}
+
+/*
+    EXT_PRINT_STDOUT    = stdout or its equivalent (may be a
+                          console window under MS Windows)
+    EXT_PRINT_STDERR    = stderr or its equivalent (may be a
+                          console window under MS Windows)
+    EXT_PRINT_ALTERNATE = an internal character array; see
+                          `alternate-debugging-output'
+    EXT_PRINT_MSWINDOWS = Under MS Windows, the "debugging output" that
+                          debuggers can hook into; uses OutputDebugString()
+                          system call
+    EXT_PRINT_ALL       = all of the above except stdout
+*/
+
+enum ext_print
+  {
+    EXT_PRINT_STDOUT = 1,
+    EXT_PRINT_STDERR = 2,
+    EXT_PRINT_ALTERNATE = 4,
+    EXT_PRINT_MSWINDOWS = 8,
+    EXT_PRINT_ALL = 14
+  };
+
+static void
+write_string_to_external_output (const Ibyte *ptr, Bytecount len,
+				 int dest)
+{
+  if (dest & EXT_PRINT_STDOUT)
+    write_string_to_stdio_stream (stdout, 0, ptr, len, 1);
+  if (dest & EXT_PRINT_STDERR)
+    write_string_to_stdio_stream (stderr, 0, ptr, len, 1);
+  if (dest & EXT_PRINT_ALTERNATE)
+    write_string_to_alternate_debugging_output (ptr, len);
+#ifdef WIN32_NATIVE
+  if (dest & EXT_PRINT_MSWINDOWS)
+    write_string_to_mswindows_debugging_output (ptr, len);
+#endif
+}
+
+/* #### The following function should make use of a call to the
+   emacs_vsprintf_*() functions rather than just using vsprintf.  This is
+   the only way to ensure that I18N3 works properly (many implementations
+   of the *printf() functions, including the ones included in glibc, do not
+   implement the %###$ argument-positioning syntax).
 
    Note, however, that to do this, we'd have to
 
@@ -204,11 +264,14 @@
    called from fatal_error_signal().
 
    2) (to be really correct) make a new lstream that outputs using
-   mswindows_output_console_string().  */
+   mswindows_output_console_string().
+
+   3) A reasonable compromise might be to use emacs_vsprintf() when we're
+   in a safe state, and when not, use plain vsprintf(). */
 
 static void
-std_handle_out_va (FILE *stream, const CIbyte *fmt, va_list args,
-		   int debug_output_as_well)
+write_string_to_external_output_va (const CIbyte *fmt, va_list args,
+				    int dest)
 {
   Ibyte kludge[8192];
   Bytecount kludgelen;
@@ -217,15 +280,7 @@
     fmt = GETTEXT (fmt);
   vsprintf ((CIbyte *) kludge, fmt, args);
   kludgelen = qxestrlen (kludge);
-
-  write_string_to_stdio_stream (stream, 0, kludge, kludgelen, 1);
-  if (debug_output_as_well)
-    {
-      write_string_to_alternate_debugging_output (kludge, kludgelen);
-#ifdef WIN32_NATIVE
-      write_string_to_mswindows_debugging_output (kludge, kludgelen);
-#endif
-    }
+  write_string_to_external_output (kludge, kludgelen, dest);
 }
 
 /* Output portably to stderr or its equivalent (i.e. may be a console
@@ -240,7 +295,7 @@
 {
   va_list args;
   va_start (args, fmt);
-  std_handle_out_va (stderr, fmt, args, 0);
+  write_string_to_external_output_va (fmt, args, EXT_PRINT_STDERR);
   va_end (args);
 }
 
@@ -252,7 +307,18 @@
 {
   va_list args;
   va_start (args, fmt);
-  std_handle_out_va (stdout, fmt, args, 0);
+  write_string_to_external_output_va (fmt, args, EXT_PRINT_STDOUT);
+  va_end (args);
+}
+
+/* Output portably to print destination as specified by DEST. */
+
+void
+external_out (int dest, const CIbyte *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  write_string_to_external_output_va (fmt, args, dest);
   va_end (args);
 }
 
@@ -266,7 +332,7 @@
 {
   va_list args;
   va_start (args, fmt);
-  std_handle_out_va (stderr, fmt, args, 1);
+  write_string_to_external_output_va (fmt, args, EXT_PRINT_ALL);
   va_end (args);
 }
 
@@ -277,7 +343,7 @@
   va_start (args, fmt);
 
   stderr_out ("\nXEmacs: fatal error: ");
-  std_handle_out_va (stderr, fmt, args, 0);
+  write_string_to_external_output_va (fmt, args, EXT_PRINT_STDERR);
   stderr_out ("\n");
 
   va_end (args);
@@ -1812,7 +1878,7 @@
 }
 
 static void
-write_string_to_alternate_debugging_output (Ibyte *str, Bytecount len)
+write_string_to_alternate_debugging_output (const Ibyte *str, Bytecount len)
 {
   int extlen;
   const Extbyte *extptr;
@@ -1832,6 +1898,35 @@
   alternate_do_string[alternate_do_pointer] = 0;
 }
 
+
+DEFUN ("set-device-clear-left-side", Fset_device_clear_left_side, 2, 2, 0, /*
+Set whether to output a newline before the next output to a stream device.
+This will happen only if the most recently-outputted character was not
+a newline -- i.e. it will make sure the left side is "clear" of text.
+*/
+       (device, value))
+{
+  if (!NILP (device))
+    CHECK_LIVE_DEVICE (device);
+  if (NILP (device) || DEVICE_STREAM_P (XDEVICE (device)))
+    /* #### This should be per-device */
+    stdout_clear_before_next_output = !NILP (value);
+  return Qnil;
+}
+
+DEFUN ("device-left-side-clear-p", Fdevice_left_side_clear_p, 0, 1, 0, /*
+For stream devices, true if the most recent-outputted character was a newline.
+*/
+       (device))
+{
+  if (!NILP (device))
+    CHECK_LIVE_DEVICE (device);
+  if (NILP (device) || DEVICE_STREAM_P (XDEVICE (device)))
+    /* #### This should be per-device */
+    return stdout_needs_newline ? Qt : Qnil;
+  return Qnil;
+}
+
 DEFUN ("external-debugging-output", Fexternal_debugging_output, 1, 3, 0, /*
 Write CHAR-OR-STRING to stderr or stdout.
 If optional arg STDOUT-P is non-nil, write to stdout; otherwise, write
@@ -1917,9 +2012,14 @@
 static int debug_print_level    = 15;
 static int debug_print_readably = -1;
 
-/* Debugging kludge -- unbuffered */
+/* Print an object, `prin1'-style, to various possible debugging outputs.
+   Make sure it's completely unbuffered so that, in the event of a crash
+   somewhere, we see as much as possible that happened before it.
+
+
+   */
 static void
-debug_print_no_newline (Lisp_Object debug_print_obj)
+debug_prin1 (Lisp_Object debug_print_obj, int flags)
 {
   /* This function can GC */
 
@@ -1938,13 +2038,17 @@
     internal_bind_lisp_object (&Vprint_level, make_int (debug_print_level));
   /* #### Do we need this?  It was in the old code. */
   internal_bind_lisp_object (&Vinhibit_quit, Vinhibit_quit);
-  
-  print_internal (debug_print_obj, Qexternal_debugging_output, 1);
-  alternate_do_pointer = 0;
-  print_internal (debug_print_obj, Qalternate_debugging_output, 1);
+
+  if ((flags & EXT_PRINT_STDOUT) || (flags & EXT_PRINT_STDERR))
+    print_internal (debug_print_obj, Qexternal_debugging_output, 1);
+  if (flags & EXT_PRINT_ALTERNATE)
+    print_internal (debug_print_obj, Qalternate_debugging_output, 1);
 #ifdef WIN32_NATIVE
-  /* Write out to the debugger, as well */
-  print_internal (debug_print_obj, Qmswindows_debugging_output, 1);
+  if (flags & EXT_PRINT_MSWINDOWS)
+    {
+      /* Write out to the debugger, as well */
+      print_internal (debug_print_obj, Qmswindows_debugging_output, 1);
+    }
 #endif
 
   unbind_to (specdepth);
@@ -2023,6 +2127,31 @@
   inhibit_non_essential_printing_operations = 0;
 }
 
+static void
+ext_print_begin (int dest)
+{
+  if (dest & EXT_PRINT_ALTERNATE)
+    alternate_do_pointer = 0;
+  if (dest & (EXT_PRINT_STDERR | EXT_PRINT_STDOUT))
+    stdout_clear_before_next_output = 1;
+}
+
+static void
+ext_print_end (int dest)
+{
+  if (dest & (EXT_PRINT_MSWINDOWS | EXT_PRINT_STDERR | EXT_PRINT_STDOUT))
+    external_out (dest & (EXT_PRINT_MSWINDOWS | EXT_PRINT_STDERR |
+			  EXT_PRINT_STDOUT), "\n");
+}
+
+static void
+external_debug_print (Lisp_Object object, int dest)
+{
+  ext_print_begin (dest);
+  debug_prin1 (object, dest);
+  ext_print_end (dest);
+}
+
 void
 debug_p3 (Lisp_Object obj)
 {
@@ -2035,8 +2164,7 @@
 void
 debug_print (Lisp_Object debug_print_obj)
 {
-  debug_print_no_newline (debug_print_obj);
-  debug_out ("\n");
+  external_debug_print (debug_print_obj, EXT_PRINT_ALL);
 }
 
 /* Getting tired of typing debug_print() ... */
@@ -2047,6 +2175,16 @@
   debug_print (debug_print_obj);
 }
 
+/* Alternate debug printer: Return a char * pointer to the output */
+char *dpa (Lisp_Object debug_print_obj);
+char *
+dpa (Lisp_Object debug_print_obj)
+{
+  external_debug_print (debug_print_obj, EXT_PRINT_ALTERNATE);
+  
+  return alternate_do_string;
+}
+
 /* Debugging kludge -- unbuffered */
 /* This function provided for the benefit of the debugger.  */
 void
@@ -2097,7 +2235,7 @@
 	}
       if (COMPILED_FUNCTIONP (*bt->function))
 	{
-#if defined(COMPILED_FUNCTION_ANNOTATION_HACK)
+#if defined (COMPILED_FUNCTION_ANNOTATION_HACK)
 	  Lisp_Object ann =
 	    compiled_function_annotation (XCOMPILED_FUNCTION (*bt->function));
 #else
@@ -2106,7 +2244,7 @@
 	  if (!NILP (ann))
 	    {
 	      debug_out ("<compiled-function from ");
-	      debug_print_no_newline (ann);
+	      debug_prin1 (ann, EXT_PRINT_ALL);
 	      debug_out (">");
 	    }
 	  else
@@ -2115,7 +2253,7 @@
 	    }
 	}
       else
-	debug_print_no_newline (*bt->function);
+	debug_prin1 (*bt->function, EXT_PRINT_ALL);
       first = 0;
       length--;
       bt = bt->next;
@@ -2145,6 +2283,8 @@
   DEFSUBR (Fterpri);
   DEFSUBR (Fwrite_char);
   DEFSUBR (Falternate_debugging_output);
+  DEFSUBR (Fset_device_clear_left_side);
+  DEFSUBR (Fdevice_left_side_clear_p);
   DEFSUBR (Fexternal_debugging_output);
   DEFSUBR (Fopen_termscript);
   DEFSYMBOL (Qexternal_debugging_output);