/* Lisp object printing and output streams.
Copyright (C) 1985, 1986, 1988, 1992-1995 Free Software Foundation, Inc.
- Copyright (C) 1995, 1996 Ben Wing.
+ Copyright (C) 1995, 1996, 2000 Ben Wing.
This file is part of XEmacs.
#include "insdel.h"
#include "lstream.h"
#include "sysfile.h"
+#ifdef WINDOWSNT
+#include "console-msw.h"
+#endif
#include <limits.h>
#include <float.h>
int stdout_needs_newline;
-/* Write a string (in internal format) to stdio stream STREAM. */
-
-void
-write_string_to_stdio_stream (FILE *stream, struct console *con,
- const Bufbyte *str,
- Bytecount offset, Bytecount len,
- Lisp_Object coding_system)
+static void
+std_handle_out_external (FILE *stream, Lisp_Object lstream,
+ const Extbyte *extptr, Extcount extlen,
+ /* is this really stdout/stderr?
+ (controls termscript writing) */
+ int output_is_std_handle,
+ int must_flush)
{
- Extcount extlen;
- const Extbyte *extptr;
-
- TO_EXTERNAL_FORMAT (DATA, (str + offset, len),
- ALLOCA, (extptr, extlen),
- coding_system);
if (stream)
{
- fwrite (extptr, 1, extlen, stream);
#ifdef WINDOWSNT
- /* Q122442 says that pipes are "treated as files, not as
- devices", and that this is a feature. Before I found that
- article, I thought it was a bug. Thanks MS, I feel much
- better now. - kkm */
- if (stream == stdout || stream == stderr)
- fflush (stream);
+ /* we typically have no useful stdout/stderr under windows if we're
+ being invoked graphically. */
+ if (!noninteractive)
+ msw_output_console_string (extptr, extlen);
+ else
+#endif
+ {
+ fwrite (extptr, 1, extlen, stream);
+#ifdef WINDOWSNT
+ /* Q122442 says that pipes are "treated as files, not as
+ devices", and that this is a feature. Before I found that
+ article, I thought it was a bug. Thanks MS, I feel much
+ better now. - kkm */
+ must_flush = 1;
#endif
+ if (must_flush)
+ fflush (stream);
+ }
}
else
- {
- assert (CONSOLE_TTY_P (con));
- Lstream_write (XLSTREAM (CONSOLE_TTY_DATA (con)->outstream),
- extptr, extlen);
- }
- if (stream == stdout || stream == stderr ||
- (!stream && CONSOLE_TTY_DATA (con)->is_stdio))
+ Lstream_write (XLSTREAM (lstream), extptr, extlen);
+
+ if (output_is_std_handle)
{
if (termscript)
{
}
}
+/* #### The following function should be replaced a call to the
+ emacs_doprnt_*() 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).
+
+ Note, however, that to do this, we'd have to
+
+ 1) pre-allocate all the lstreams and do whatever else was necessary
+ to make sure that no allocation occurs, since these functions may be
+ called from fatal_error_signal().
+
+ 2) (to be really correct) make a new lstream that outputs using
+ msw_output_console_string(). */
+
+static int
+std_handle_out_va (FILE *stream, const char *fmt, va_list args)
+{
+ Bufbyte kludge[8192];
+ Extbyte *extptr;
+ Extcount extlen;
+ int retval;
+
+ retval = vsprintf ((char *) kludge, fmt, args);
+ TO_EXTERNAL_FORMAT (DATA, (kludge, strlen ((char *) kludge)),
+ ALLOCA, (extptr, extlen),
+ Qnative);
+ std_handle_out_external (stream, Qnil, extptr, extlen, 1, 1);
+ return retval;
+}
+
+/* Output portably to stderr or its equivalent; call GETTEXT on the
+ format string. Automatically flush when done. */
+
+int
+stderr_out (const char *fmt, ...)
+{
+ int retval;
+ va_list args;
+ va_start (args, fmt);
+ retval = std_handle_out_va (stderr, GETTEXT (fmt), args);
+ va_end (args);
+ return retval;
+}
+
+/* Output portably to stdout or its equivalent; call GETTEXT on the
+ format string. Automatically flush when done. */
+
+int
+stdout_out (const char *fmt, ...)
+{
+ int retval;
+ va_list args;
+ va_start (args, fmt);
+ retval = std_handle_out_va (stdout, GETTEXT (fmt), args);
+ va_end (args);
+ return retval;
+}
+
+DOESNT_RETURN
+fatal (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+
+ stderr_out ("\nXEmacs: ");
+ std_handle_out_va (stderr, GETTEXT (fmt), args);
+ stderr_out ("\n");
+
+ va_end (args);
+ exit (1);
+}
+
+/* Write a string (in internal format) to stdio stream STREAM. */
+
+void
+write_string_to_stdio_stream (FILE *stream, struct console *con,
+ const Bufbyte *str,
+ Bytecount offset, Bytecount len,
+ Lisp_Object coding_system,
+ int must_flush)
+{
+ Extcount extlen;
+ const Extbyte *extptr;
+
+ /* #### yuck! sometimes this function is called with string data,
+ and the following call may gc. */
+ {
+ Bufbyte *puta = (Bufbyte *) alloca (len);
+ memcpy (puta, str + offset, len);
+ TO_EXTERNAL_FORMAT (DATA, (puta, len),
+ ALLOCA, (extptr, extlen),
+ coding_system);
+ }
+
+ if (stream)
+ std_handle_out_external (stream, Qnil, extptr, extlen,
+ stream == stdout || stream == stderr, must_flush);
+ else
+ {
+ assert (CONSOLE_TTY_P (con));
+ std_handle_out_external (0, CONSOLE_TTY_DATA (con)->outstream,
+ extptr, extlen,
+ CONSOLE_TTY_DATA (con)->is_stdio, must_flush);
+ }
+}
+
/* Write a string to the output location specified in FUNCTION.
Arguments NONRELOC, RELOC, OFFSET, and LEN are as in
buffer_insert_string_1() in insdel.c. */
else if (EQ (function, Qt) || EQ (function, Qnil))
{
write_string_to_stdio_stream (stdout, 0, newnonreloc, offset, len,
- Qterminal);
+ Qterminal, print_unbuffered);
}
else
{
to stderr. You can use this function to write directly to the terminal.
This function can be used as the STREAM argument of Fprint() or the like.
+Under MS Windows, this writes output to the console window (which is
+created, if necessary), unless XEmacs is being run noninteractively
+(i.e. using the `-batch' argument).
+
If you have opened a termscript file (using `open-termscript'), then
the output also will be logged to this file.
*/
write_string_to_stdio_stream (file, con,
XSTRING_DATA (char_or_string),
0, XSTRING_LENGTH (char_or_string),
- Qterminal);
+ Qterminal, 1);
else
{
Bufbyte str[MAX_EMCHAR_LEN];
CHECK_CHAR_COERCE_INT (char_or_string);
len = set_charptr_emchar (str, XCHAR (char_or_string));
- write_string_to_stdio_stream (file, con, str, 0, len, Qterminal);
+ write_string_to_stdio_stream (file, con, str, 0, len, Qterminal, 1);
}
return char_or_string;
{
debug_print_no_newline (debug_print_obj);
stderr_out ("\n");
- fflush (stderr);
}
/* Debugging kludge -- unbuffered */
Fbacktrace (Qexternal_debugging_output, Qt);
stderr_out ("\n");
- fflush (stderr);
Vinhibit_quit = old_inhibit_quit;
Vprint_level = old_print_level;
int first = 1;
struct backtrace *bt = backtrace_list;
stderr_out (" [");
- fflush (stderr);
while (length > 0 && bt)
{
if (!first)
{
stderr_out (", ");
- fflush (stderr);
}
if (COMPILED_FUNCTIONP (*bt->function))
{
if (!NILP (ann))
{
stderr_out ("<compiled-function from ");
- fflush (stderr);
debug_print_no_newline (ann);
stderr_out (">");
- fflush (stderr);
}
else
{
stderr_out ("<compiled-function of unknown origin>");
- fflush (stderr);
}
}
else
bt = bt->next;
}
stderr_out ("]\n");
- fflush (stderr);
}
#endif /* debugging kludge */