Mercurial > hg > xemacs-beta
diff src/emacs.c @ 771:943eaba38521
[xemacs-hg @ 2002-03-13 08:51:24 by ben]
The big ben-mule-21-5 check-in!
Various files were added and deleted. See CHANGES-ben-mule.
There are still some test suite failures. No crashes, though.
Many of the failures have to do with problems in the test suite itself
rather than in the actual code. I'll be addressing these in the next
day or so -- none of the test suite failures are at all critical.
Meanwhile I'll be trying to address the biggest issues -- i.e. build
or run failures, which will almost certainly happen on various platforms.
All comments should be sent to ben@xemacs.org -- use a Cc: if necessary
when sending to mailing lists. There will be pre- and post- tags,
something like
pre-ben-mule-21-5-merge-in, and
post-ben-mule-21-5-merge-in.
author | ben |
---|---|
date | Wed, 13 Mar 2002 08:54:06 +0000 |
parents | fdefd0186b75 |
children | 79940b592197 |
line wrap: on
line diff
--- a/src/emacs.c Fri Mar 08 13:33:14 2002 +0000 +++ b/src/emacs.c Wed Mar 13 08:54:06 2002 +0000 @@ -2,7 +2,7 @@ Copyright (C) 1985, 1986, 1987, 1992, 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 2000 Ben Wing. + Copyright (C) 2000, 2001, 2002 Ben Wing. This file is part of XEmacs. @@ -24,10 +24,12 @@ /* Synched up with: Mule 2.0, FSF 19.28. */ /* Capsule summary of the various releases of Lucid Emacs/XEmacs and - FSF/GNU Emacs. Provided here for use in cross-referencing version - releases and dates in comments, esp. in the authorship comments at - the beginning of each file. More information about history can be - found in the beginning of the Internals Manual and in the About page. + FSF/GNU Emacs. (Copied from the Internals Manual, where the + canonical version lives.) Provided here for use in cross-referencing + version releases and dates in comments, esp. in the authorship + comments at the beginning of each file. More information about + history can be found in the beginning of the Internals Manual and + in the About page. -- A time line for Lucid Emacs/XEmacs is @@ -54,9 +56,74 @@ version 20.1 (not released to the net) April 15, 1997. version 20.2 released May 16, 1997. version 19.16 released October 31, 1997. -version 20.3 (the first stable version of XEmacs 20.x) released - November 30, 1997. +version 20.3 (the first stable version of XEmacs 20.x) released November 30, +1997. version 20.4 released February 28, 1998. +version 21.0.60 released December 10, 1998. (The version naming scheme was +changed at this point: [a] the second version number is odd for stable +versions, even for beta versions; [b] a third version number is added, +replacing the "beta xxx" ending for beta versions and allowing for +periodic maintenance releases for stable versions. Therefore, 21.0 was +never "officially" released; similarly for 21.2, etc.) +version 21.0.61 released January 4, 1999. +version 21.0.63 released February 3, 1999. +version 21.0.64 released March 1, 1999. +version 21.0.65 released March 5, 1999. +version 21.0.66 released March 12, 1999. +version 21.0.67 released March 25, 1999. +version 21.1.2 released May 14, 1999. (This is the followup to 21.0.67. +The second version number was bumped to indicate the beginning of the +"stable" series.) +version 21.1.3 released June 26, 1999. +version 21.1.4 released July 8, 1999. +version 21.1.6 released August 14, 1999. (There was no 21.1.5.) +version 21.1.7 released September 26, 1999. +version 21.1.8 released November 2, 1999. +version 21.1.9 released February 13, 2000. +version 21.1.10 released May 7, 2000. +version 21.1.10a released June 24, 2000. +version 21.1.11 released July 18, 2000. +version 21.1.12 released August 5, 2000. +version 21.1.13 released January 7, 2001. +version 21.1.14 released January 27, 2001. +version 21.2.9 released February 3, 1999. +version 21.2.10 released February 5, 1999. +version 21.2.11 released March 1, 1999. +version 21.2.12 released March 5, 1999. +version 21.2.13 released March 12, 1999. +version 21.2.14 released May 14, 1999. +version 21.2.15 released June 4, 1999. +version 21.2.16 released June 11, 1999. +version 21.2.17 released June 22, 1999. +version 21.2.18 released July 14, 1999. +version 21.2.19 released July 30, 1999. +version 21.2.20 released November 10, 1999. +version 21.2.21 released November 28, 1999. +version 21.2.22 released November 29, 1999. +version 21.2.23 released December 7, 1999. +version 21.2.24 released December 14, 1999. +version 21.2.25 released December 24, 1999. +version 21.2.26 released December 31, 1999. +version 21.2.27 released January 18, 2000. +version 21.2.28 released February 7, 2000. +version 21.2.29 released February 16, 2000. +version 21.2.30 released February 21, 2000. +version 21.2.31 released February 23, 2000. +version 21.2.32 released March 20, 2000. +version 21.2.33 released May 1, 2000. +version 21.2.34 released May 28, 2000. +version 21.2.35 released July 19, 2000. +version 21.2.36 released October 4, 2000. +version 21.2.37 released November 14, 2000. +version 21.2.38 released December 5, 2000. +version 21.2.39 released December 31, 2000. +version 21.2.40 released January 8, 2001. +version 21.2.41 released January 17, 2001. +version 21.2.42 released January 20, 2001. +version 21.2.43 released January 26, 2001. +version 21.2.44 released February 8, 2001. +version 21.2.45 released February 23, 2001. +version 21.2.46 released March 21, 2001. -- A time line for GNU Emacs version 19 is @@ -179,15 +246,12 @@ #include "systty.h" #include "sysfile.h" #include "systime.h" +#include "sysproc.h" /* for qxe_getpid() */ #ifdef PDUMP #include "dumper.h" #endif -#ifndef SEPCHAR -#define SEPCHAR ':' -#endif - #ifdef QUANTIFY #include <quantify.h> #endif @@ -196,17 +260,12 @@ #include "sysdll.h" #endif -#if defined (HAVE_LOCALE_H) && \ - (defined (I18N2) || defined (I18N3) || defined (I18N4)) -#include <locale.h> -#endif - #ifdef TOOLTALK #include TT_C_H_FILE #endif -#if defined (WIN32_NATIVE) -#include "nt.h" +#if defined (WIN32_NATIVE) || defined (CYGWIN) +#include "syswindows.h" #endif /* For PATH_EXEC */ @@ -296,7 +355,6 @@ Lisp_Object Vconfigure_info_path; Lisp_Object Vinternal_error_checking; Lisp_Object Vmail_lock_methods, Vconfigure_mail_lock_method; -Lisp_Object Vpath_separator; /* The default base directory XEmacs is installed under. */ Lisp_Object Vconfigure_exec_prefix_directory, Vconfigure_prefix_directory; @@ -318,7 +376,7 @@ /* Type of display specified. We cannot use a Lisp symbol here because Lisp symbols may not initialized at the time that we set this variable. */ -const char *display_use; +const Char_ASCII *display_use; /* If non-zero, then the early error handler will only print the error message and exit. */ @@ -400,64 +458,16 @@ extern Lisp_Object Vlisp_EXEC_SUFFIXES; - - -/* Ben's capsule summary about expected and unexpected exits from XEmacs. - - Expected exits occur when the user directs XEmacs to exit, for example - by pressing the close button on the only frame in XEmacs, or by typing - C-x C-c. This runs `save-buffers-kill-emacs', which saves any necessary - buffers, and then exits using the primitive `kill-emacs'. - - However, unexpected exits occur in a few different ways: - - -- a memory access violation or other hardware-generated exception - occurs. This is the worst possible problem to deal with, because - the fault can occur while XEmacs is in any state whatsoever, even - quite unstable ones. As a result, we need to be *extremely* careful - what we do. - -- we are using one X display (or if we've used more, we've closed the - others already), and some hardware or other problem happens and - suddenly we've lost our connection to the display. In this situation, - things are not so dire as in the last one; our code itself isn't - trashed, so we can continue execution as normal, after having set - things up so that we can exit at the appropriate time. Our exit - still needs to be of the emergency nature; we have no displays, so - any attempts to use them will fail. We simply want to auto-save - (the single most important thing to do during shut-down), do minimal - cleanup of stuff that has an independent existence outside of XEmacs, - and exit. - - Currently, both unexpected exit scenarios described above set - preparing_for_armageddon to indicate that nonessential and possibly - dangerous things should not be done, specifically: - - -- no garbage collection. - -- no hooks are run. - -- no messages of any sort from autosaving. - -- autosaving tries harder, ignoring certain failures. - -- existing frames are not deleted. - - (Also, all places that set preparing_for_armageddon also - set dont_check_for_quit. This happens separately because it's - also necessary to set other variables to make absolutely sure - no quitting happens.) - - In the first scenario above (the access violation), we also set - fatal_error_in_progress. This causes more things to not happen: - - -- assertion failures do not abort. - -- printing code does not do code conversion or gettext when - printing to stdout/stderr. -*/ - /* Nonzero if handling a fatal error already. */ int fatal_error_in_progress; -/* Non-nil means we're going down, so we better not run any hooks +/* Nonzero means we're going down, so we better not run any hooks or do other non-essential stuff. */ int preparing_for_armageddon; +/* Nonzero means we're in an unstable situation and need to skip + i18n conversions and such during printing. */ +int inhibit_non_essential_printing_operations; static JMP_BUF run_temacs_catch; @@ -467,181 +477,15 @@ static int run_temacs_argv_size; static int run_temacs_args_size; -static void shut_down_emacs (int sig, Lisp_Object stuff, int no_auto_save); - -static void -ensure_no_quitting_from_now_on (void) -{ - /* make sure no quitting from now on!! */ - dont_check_for_quit = 1; - Vinhibit_quit = Qt; - Vquit_flag = Qnil; -} - -/* Handle bus errors, illegal instruction, etc. */ -SIGTYPE -fatal_error_signal (int sig) -{ - fatal_error_in_progress++; - preparing_for_armageddon = 1; - - ensure_no_quitting_from_now_on (); - - /* Unblock the signal so that if the same signal gets sent in the - code below, we avoid a deadlock. */ - EMACS_UNBLOCK_SIGNAL (sig); - - /* Only try auto-saving first time through. If we crash in auto-saving, - don't do it again. */ - if (fatal_error_in_progress == 1) - { - Fdo_auto_save (Qt, Qnil); /* do this before anything hazardous */ - /* Do this so that the variable has the same value of 2 regardless of - whether we made it through auto-saving correctly. */ - fatal_error_in_progress++; - } - else if (fatal_error_in_progress == 2) - stderr_out ("WARNING: Unable to auto-save your files properly.\n" - "Some or all may in fact have been auto-saved.\n" - "\n"); - - /* Now, reset our signal handler, so the next time, we just die. - Don't do this before auto-saving. */ - EMACS_SIGNAL (sig, SIG_DFL); - - /* Keep in mind that there's more than one signal that we can crash - on. */ - /* If fatal error occurs in code below, avoid infinite recursion. */ - if (fatal_error_in_progress <= 2) - { - shut_down_emacs (sig, Qnil, 1); - stderr_out ("\nLisp backtrace follows:\n\n"); - Fbacktrace (Qexternal_debugging_output, Qt); -# if 0 /* This is evil, rarely useful, and causes grief in some cases. */ - /* Check for Sun-style stack printing via /proc */ - { - const char *pstack = "/usr/proc/bin/pstack"; - if (access (pstack, X_OK) == 0) - { - char buf[100]; - stderr_out ("\nC backtrace follows:\n" - "(A real debugger may provide better information)\n\n"); - sprintf (buf, "%s %d >&2", pstack, (int)getpid()); - system (buf); - } - } -# endif - } - /* Signal the same code; this time it will really be fatal. */ - kill (getpid (), sig); - SIGRETURN; -} - #ifdef _MSC_VER - -static DWORD -mswindows_handle_hardware_exceptions (DWORD code) -{ - if (code != STATUS_ACCESS_VIOLATION && code != STATUS_ILLEGAL_INSTRUCTION - && code != STATUS_PRIVILEGED_INSTRUCTION - && code != STATUS_DATATYPE_MISALIGNMENT) - return EXCEPTION_CONTINUE_SEARCH; - - /* I don't know if this filter is still wrapped in the outer __try, but - it doesn't hurt to have another one. --ben - And it lets us control more exactly what we really want to do in such - a situation. */ - __try - { - fatal_error_in_progress++; - preparing_for_armageddon = 1; - - ensure_no_quitting_from_now_on (); - - /* Only try auto-saving first time through. If we crash in auto-saving, - don't do it again. */ - if (fatal_error_in_progress == 1) - { - Fdo_auto_save (Qt, Qnil); /* do this before anything hazardous */ - /* Do this so that the variable has the same value of 2 regardless of - whether we made it through auto-saving correctly. */ - fatal_error_in_progress++; - } - else if (fatal_error_in_progress == 2) - stderr_out ("WARNING: Unable to auto-save your files properly.\n" - "Some or all may in fact have been auto-saved.\n" - "\n"); - - /* If fatal error occurs in code below, avoid infinite recursion. */ - if (fatal_error_in_progress <= 2) - { - shut_down_emacs (-1, Qnil, 1); - stderr_out ("\nLisp backtrace follows:\n\n"); - Fbacktrace (Qexternal_debugging_output, Qt); - } - } - /* VC++ documentation says that - GetExceptionCode() cannot be called inside the filter itself. */ - - /* __except (mswindows_handle_hardware_exceptions (GetExceptionCode ())) {} - - The line above is original. Unfortunately, when an error is tripped - inside of the handler (e.g. during Fbacktrace()), and the handler for - the handler is invoked, it correctly notices that something is amiss - and it should just return -- but it returns EXCEPTION_CONTINUE_SEARCH, - which causes the debugger to be invoked debugging the handler code in - this function -- and WITH THE STACK UNWOUND so that you see main() - calling mswindows_handle_hardware_exceptions(), calling Fbacktrace(), - and a crash a couple of frames in -- AND NO SIGN OF THE ORIGINAL CRASH! - - There's some real weirdness going on in the stack handling -- unlike - in Unix, where further crashes just keep adding to the stack, it seems - that under the structured-exception-handling, the stack can actually - bounce back and forth between the full stack at the location of the - exception and the unwound stack at the place where the __try clause was - established. I don't completely understand it. What I do know is that - returning EXCEPTION_EXECUTE_HANDLER on nested crash has the effect of - aborting execution of the handler and going back to the outer filter - function, which returns EXCEPTION_CONTINUE_SEARCH and everything is - hunky-dorey -- your debugger sees a crash at the right location with - the right stack. - - I'm leaving in the trickier Unix-like code in the handler; someone who - understands better than me how the stack works in these handlers could - fix it up more. As it is, it works pretty well, so I'm not likely to - touch it more. --ben - */ - - __except (EXCEPTION_EXECUTE_HANDLER) {} - - - /* pretend we didn't handle this, so that the debugger is invoked and/or - the normal GPF box appears. */ - return EXCEPTION_CONTINUE_SEARCH; -} - -#endif /* _MSC_VER */ +static DWORD mswindows_handle_hardware_exceptions (DWORD code); +#endif - -#ifdef SIGDANGER - -/* Handler for SIGDANGER. */ -SIGTYPE -memory_warning_signal (int sig) -{ - /* #### bad bad bad; this function shouldn't do anything except - set a flag, or weird corruption could happen. */ - EMACS_SIGNAL (sig, memory_warning_signal); - - malloc_warning - (GETTEXT ("Operating system warns that virtual memory is running low.\n")); - - /* It might be unsafe to call do_auto_save now. */ - force_auto_save_soon (); -} -#endif /* SIGDANGER */ - +/************************************************************************/ +/* Functions to handle arguments */ +/************************************************************************/ + /* Code for dealing with Lisp access to the Unix command line */ static Lisp_Object @@ -661,8 +505,8 @@ Extbyte full_exe_path[PATH_MAX]; Lisp_Object fullpath; - GetModuleFileName (NULL, full_exe_path, PATH_MAX); - fullpath = build_ext_string (full_exe_path, Qmswindows_tstr); + qxeGetModuleFileName (NULL, full_exe_path, PATH_MAX); + fullpath = build_tstr_string (full_exe_path); result = Fcons (fullpath, result); #if defined(HAVE_SHLIB) { @@ -752,12 +596,6 @@ } -#ifdef I18N4 - /* #### - don't know why I18N4 on SunOS/JLE - can't deal with this. It's a potential - bug that needs to be looked at. */ -# undef RUN_TIME_REMAP -#endif /* Test whether the next argument in ARGV matches SSTR or a prefix of LSTR (at least MINLEN characters). If so, then if VALPTR is non-null @@ -822,6 +660,11 @@ } } + +/************************************************************************/ +/* main and friends: XEmacs startup */ +/************************************************************************/ + /* Make stack traces always identify version + configuration */ #define main_1 STACK_TRACE_EYE_CATCHER @@ -829,9 +672,10 @@ inline it, which would make it not show up in stack traces. The restart argument is a flag that indicates that main_1 is now - being called for the second time in this invocation of xemacs; this can - only happen in an xemacs that is not loaded with dumped data (temacs - with the conventional dumper or xemacs -nd with the pdumper). See + being called for the second time in this invocation of xemacs; this + happens as a result of using `run-temacs' in the command line, when + invoking a bare (without dumped data) XEmacs (i.e. `temacs' with + the conventional dumper or `xemacs -nd' with the pdumper). See Frun_emacs_from_temacs(). restart interacts with initialized as follows (per Olivier Galibert): @@ -840,7 +684,8 @@ initialized==0 => temacs initialized!=0 && restart!=0 => run-temacs - initialized!=0 && restart==0 => xemacs/post pdump_load() + initialized!=0 && restart==0 => either xemacs after conventional dump, + or xemacs post pdump_load() */ DECLARE_DOESNT_RETURN (main_1 (int, char **, char **, int)); DOESNT_RETURN @@ -866,6 +711,7 @@ #endif /* not SYSTEM_MALLOC or HAVE_LIBMCHECK or DOUG_LEA_MALLOC */ noninteractive = 0; + inhibit_non_essential_printing_operations = 1; #ifdef NeXT /* 19-Jun-1995 -baw @@ -954,14 +800,14 @@ #endif exit (0); } - + /* Handle the -t switch, which specifies filename to use as terminal */ { - char *term; + Extbyte *term; if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args)) { - close (0); - close (1); + retry_close (0); + retry_close (1); if (open (term, O_RDWR | OPEN_BINARY, 2) < 0) fatal ("%s: %s", term, strerror (errno)); dup (0); @@ -995,6 +841,16 @@ noninteractive = 1; } +#ifdef WIN32_NATIVE + /* Handle the -nuni switch, which forces XEmacs to use the ANSI + versions of Unicode-split API's even on Windows NT, which has + full Unicode support. This helps flush out problems in the code + we've written to convert between ANSI and Unicode. */ + if (argmatch (argv, argc, "-nuni", "--no-unicode-lib-calls", 6, NULL, + &skip_args)) + no_mswin_unicode_lib_calls = 1; +#endif /* WIN32_NATIVE */ + /* #### is it correct that -debug-paths is handled here (and presumably removed), and then checked again below? */ if (argmatch (argv, argc, "-debug-paths", "--debug-paths", @@ -1123,7 +979,7 @@ } #endif #ifdef HAVE_MS_WINDOWS - if (strcmp(display_use, "x") != 0) + if (strcmp (display_use, "x") != 0) display_use = "mswindows"; #endif /* HAVE_MS_WINDOWS */ } @@ -1145,12 +1001,15 @@ init_process_times_very_early (); /* Initialize our process timers. As early as possible, of course, so we can be fairly accurate. */ - init_intl_very_early (); /* set up the locale and domain for gettext and - such. */ + +#ifdef HAVE_WIN32_CODING_SYSTEMS + init_win32_very_early (); +#endif #ifdef HAVE_MS_WINDOWS - init_mswindows_very_early (); /* Some things - like dde need to be - initialized early so that the - client doesn't give up waiting. */ + /* Depends on XEUNICODE_P, only accurate after the previous call */ + init_mswindows_dde_very_early (); /* DDE needs to be initialized early so + that the client doesn't give up + waiting. */ #endif /* Now initialize the Lisp engine and the like. Done only during @@ -1167,51 +1026,62 @@ #ifdef PDUMP if (restart) initialized = 1; - else if (nodumpfile) { - initialized = 0; - purify_flag = 1; - } else { - - /* Keep command options from getting stomped. - - Some LISP-visible options are changed by XEmacs _after_ the data is - dumped in building a --pdump XEmacs, but _before_ it is restored in - normal operation. Thus the restored values overwrite the values - XEmacs is getting at run-time. Such variables must be saved here, - and restored after loading the dumped data. - - Boy, this is ugly, but how else to do it? - */ - - /* noninteractive1 is saved in noninteractive, which isn't LISP-visible */ - int inhibit_early_packages_save = inhibit_early_packages; - int inhibit_autoloads_save = inhibit_autoloads; - int debug_paths_save = debug_paths; - /* #### Give inhibit-site-lisp a command switch? If so, uncomment: */ - /* int inhibit_site_lisp_save = inhibit_site_lisp; */ - int inhibit_site_modules_save = inhibit_site_modules; - - initialized = pdump_load (argv[0]); - - /* Now unstomp everything */ - noninteractive1 = noninteractive; - inhibit_early_packages = inhibit_early_packages_save; - inhibit_autoloads = inhibit_autoloads_save; - debug_paths = debug_paths_save; - /* #### Give inhibit-site-lisp a command switch? If so, uncomment: */ - /* inhibit_site_lisp = inhibit_site_lisp_save; */ - inhibit_site_modules = inhibit_site_modules_save; - - if (initialized) - run_temacs_argc = -1; - else + else if (nodumpfile) + { + initialized = 0; purify_flag = 1; - } + } + else + { + + /* Keep command options from getting stomped. + + Some LISP-visible options are changed by XEmacs _after_ the data is + dumped in building a --pdump XEmacs, but _before_ it is restored in + normal operation. Thus the restored values overwrite the values + XEmacs is getting at run-time. Such variables must be saved here, + and restored after loading the dumped data. + + Boy, this is ugly, but how else to do it? + */ + + /* noninteractive1 is saved in noninteractive, which isn't + LISP-visible */ + int inhibit_early_packages_save = inhibit_early_packages; + int inhibit_autoloads_save = inhibit_autoloads; + int debug_paths_save = debug_paths; + /* #### Give inhibit-site-lisp a command switch? If so, uncomment: */ + /* int inhibit_site_lisp_save = inhibit_site_lisp; */ + int inhibit_site_modules_save = inhibit_site_modules; + + initialized = pdump_load (argv[0]); + + /* Now unstomp everything */ + noninteractive1 = noninteractive; + inhibit_early_packages = inhibit_early_packages_save; + inhibit_autoloads = inhibit_autoloads_save; + debug_paths = debug_paths_save; + /* #### Give inhibit-site-lisp a command switch? If so, uncomment: */ + /* inhibit_site_lisp = inhibit_site_lisp_save; */ + inhibit_site_modules = inhibit_site_modules_save; + + if (initialized) + run_temacs_argc = -1; + else + purify_flag = 1; + } #else if (!initialized) purify_flag = 1; #endif + if (initialized) + { + /* Reset some vars that were also set during loadup (we called + these same functions below) */ + init_alloc_early (); + } + if (!initialized) { /* Initialize things so that new Lisp objects @@ -1233,6 +1103,16 @@ /* Make sure that opaque pointers can be created. */ init_opaque_once_early (); + /* Make sure that hash tables can be created. */ + init_elhash_once_early (); + + /* Make sure that eistrings can be created. */ + init_eistring_once_early (); + + /* Initialize some vars that will also be reset post-dumping + (see above) */ + init_alloc_early (); + /* Now declare all the symbols and define all the Lisp primitives. The *only* thing that the syms_of_*() functions are allowed to do @@ -1344,6 +1224,7 @@ #ifdef HAVE_SCROLLBARS syms_of_scrollbar (); #endif + syms_of_text (); #ifdef HAVE_TOOLBARS syms_of_toolbar (); #endif @@ -1354,6 +1235,7 @@ #ifdef HAVE_TTY syms_of_console_tty (); syms_of_device_tty (); + syms_of_frame_tty (); syms_of_objects_tty (); #endif @@ -1372,7 +1254,7 @@ #endif syms_of_select_gtk (); -#if defined (HAVE_MENUBARS) || defined(HAVE_SCROLLBARS) || defined(HAVE_DIALOGS) || defined(HAVE_TOOLBARS) +#ifdef HAVE_GUI_OBJECTS syms_of_gui_gtk (); #endif #endif /* HAVE_GTK */ @@ -1382,7 +1264,7 @@ syms_of_balloon_x (); #endif syms_of_device_x (); -#ifdef HAVE_DIALOGS +#ifdef HAVE_X_DIALOGS syms_of_dialog_x (); #endif syms_of_frame_x (); @@ -1392,9 +1274,10 @@ syms_of_menubar_x (); #endif syms_of_select_x (); -#if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_DIALOGS) || defined (HAVE_TOOLBARS) +#ifdef HAVE_GUI_OBJECTS syms_of_gui_x (); #endif + syms_of_intl_x (); #ifdef HAVE_XIM #ifdef XIM_XLIB syms_of_input_method_xlib (); @@ -1405,12 +1288,16 @@ #ifdef HAVE_MS_WINDOWS syms_of_console_mswindows (); syms_of_device_mswindows (); +#ifdef HAVE_DIALOGS syms_of_dialog_mswindows (); +#endif syms_of_frame_mswindows (); syms_of_objects_mswindows (); syms_of_select_mswindows (); syms_of_glyphs_mswindows (); +#ifdef HAVE_GUI_OBJECTS syms_of_gui_mswindows (); +#endif #ifdef HAVE_MENUBARS syms_of_menubar_mswindows (); #endif @@ -1422,21 +1309,18 @@ syms_of_dired_mswindows (); #endif #ifdef WIN32_NATIVE - syms_of_ntproc (); + syms_of_nt (); #endif #if defined (WIN32_NATIVE) || defined (CYGWIN) syms_of_win32 (); #endif + syms_of_file_coding (); + syms_of_unicode (); #ifdef MULE - syms_of_mule (); syms_of_mule_ccl (); syms_of_mule_charset (); -#endif -#ifdef FILE_CODING - syms_of_file_coding (); -#endif -#ifdef MULE + syms_of_mule_coding (); #ifdef HAVE_WNN syms_of_mule_wnn (); #endif @@ -1445,6 +1329,10 @@ #endif /* HAVE_CANNA */ #endif /* MULE */ +#ifdef HAVE_WIN32_CODING_SYSTEMS + syms_of_intl_win32 (); +#endif + #ifdef SYMS_SYSTEM SYMS_SYSTEM; #endif @@ -1548,7 +1436,7 @@ #ifdef HAVE_TOOLBARS console_type_create_toolbar_x (); #endif -#ifdef HAVE_DIALOGS +#ifdef HAVE_X_DIALOGS console_type_create_dialog_x (); #endif #endif /* HAVE_X_WINDOWS */ @@ -1594,6 +1482,25 @@ specifier_type_create_toolbar (); #endif + /* Now initialize the coding system types and associated symbols. + Other than the first function below, the functions may + make exactly the following function/macro calls: + + INITIALIZE_CODING_SYSTEM_TYPE() + CODING_SYSTEM_HAS_METHOD() + + For any given coding system type, the former macro must be called + before the any calls to the latter macro. */ + + coding_system_type_create (); + coding_system_type_create_unicode (); +#ifdef HAVE_WIN32_CODING_SYSTEMS + coding_system_type_create_intl_win32 (); +#endif +#ifdef MULE + coding_system_type_create_mule_coding (); +#endif + /* Now initialize the structure types and associated symbols. Other than the first function below, the functions may make exactly the following function/macro calls: @@ -1646,9 +1553,7 @@ */ lstream_type_create (); -#ifdef FILE_CODING lstream_type_create_file_coding (); -#endif #if defined (HAVE_MS_WINDOWS) && !defined(HAVE_MSG_SELECT) lstream_type_create_mswindows_selectable (); #endif @@ -1669,40 +1574,47 @@ These functions may do exactly the following: - DEFVAR_INT() - DEFVAR_LISP() - DEFVAR_BOOL() - DEFER_GETTEXT() - Dynarr_*() - Blocktype_*() - staticpro() - Fprovide(symbol) - intern() - Fput() - xmalloc() - defsymbol(), if it's absolutely necessary and you're sure that - the symbol isn't referenced anywhere else in the initialization - code - Fset() on a symbol that is unbound - assigning a symbol or constant value to a variable - using a global variable that has been initialized - earlier on in the same function - - Any of the object-creating functions in alloc.c: e.g. - - make_pure_*() - make_string() - build_string() - make_vector() - make_int() - make_extent() - alloc_lcrecord() - Fcons() - listN() - make_opaque_ptr() + -- assigning a symbol or constant value to a variable + -- using a global variable that has been initialized + earlier on in the same function + -- DEFVAR_INT() + -- DEFVAR_LISP() + -- DEFVAR_BOOL() + -- DEFER_GETTEXT() + -- staticpro*() + -- xmalloc*(), xnew*(), and friends + -- Dynarr_*() + -- Blocktype_*() + -- Fprovide(symbol) + -- intern() + -- Fput() + -- dump_add_*() + -- C library functions with no external dependencies, e.g. str*() + -- defsymbol(), if it's absolutely necessary and you're sure that + the symbol isn't referenced anywhere else in the initialization + code + -- Fset() on a symbol that is unbound + -- Any of the object-creating functions in alloc.c: e.g. + - make_string() + - build_intstring() + - build_string() + - make_vector() + - make_int() + - make_char() + - make_extent() + - alloc_lcrecord() + - Fcons() + - listN() + - make_lcrecord_list() + -- make_opaque_ptr() + -- make_lisp_hash_table() (not allowed in 21.4!) + -- certain specifier creation functions (but be careful; see + glyphs.c for examples) perhaps a few others. + NO EXTERNAL-FORMAT CONVERSIONS. + NB: Initialization or assignment should not be done here to certain variables settable from the command line. See the comment above the call to pdump_load() in main_1(). This caveat should only @@ -1741,9 +1653,9 @@ vars_of_dragdrop (); #endif vars_of_editfns (); - vars_of_elhash (); vars_of_emacs (); vars_of_eval (); + init_eval_early (); #ifdef HAVE_X_WINDOWS vars_of_event_Xt (); @@ -1759,11 +1671,13 @@ vars_of_events (); vars_of_extents (); vars_of_faces (); + vars_of_file_coding (); vars_of_fileio (); #ifdef CLASH_DETECTION vars_of_filelock (); #endif vars_of_floatfns (); + vars_of_fns (); vars_of_font_lock (); vars_of_frame (); vars_of_glyphs (); @@ -1774,6 +1688,9 @@ vars_of_indent (); vars_of_insdel (); vars_of_intl (); +#ifdef HAVE_WIN32_CODING_SYSTEMS + vars_of_intl_win32 (); +#endif #ifdef HAVE_XIM #ifdef XIM_MOTIF vars_of_input_method_motif (); @@ -1826,11 +1743,15 @@ vars_of_sound (); vars_of_symbols (); vars_of_syntax (); + vars_of_text (); #ifdef HAVE_TOOLBARS vars_of_toolbar (); #endif vars_of_undo (); vars_of_window (); +#if defined (WIN32_NATIVE) || defined (CYGWIN) + vars_of_win32 (); +#endif #ifdef HAVE_TTY vars_of_console_tty (); @@ -1865,7 +1786,7 @@ vars_of_balloon_x (); #endif vars_of_device_x (); -#ifdef HAVE_DIALOGS +#ifdef HAVE_X_DIALOGS vars_of_dialog_x (); #endif vars_of_frame_x (); @@ -1878,7 +1799,7 @@ #ifdef HAVE_SCROLLBARS vars_of_scrollbar_x (); #endif -#if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_DIALOGS) || defined (HAVE_TOOLBARS) +#if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_X_DIALOGS) || defined (HAVE_TOOLBARS) vars_of_gui_x (); #endif #endif /* HAVE_X_WINDOWS */ @@ -1906,14 +1827,13 @@ #endif /* HAVE_MS_WINDOWS */ #ifdef MULE - vars_of_mule (); vars_of_mule_ccl (); vars_of_mule_charset (); #endif -#ifdef FILE_CODING vars_of_file_coding (); -#endif + vars_of_unicode (); #ifdef MULE + vars_of_mule_coding (); #ifdef HAVE_WNN vars_of_mule_wnn (); #endif @@ -1935,7 +1855,7 @@ #endif #ifdef HAVE_POSTGRESQL - vars_of_postgresql(); + vars_of_postgresql (); #endif #ifdef HAVE_GPM @@ -1975,30 +1895,27 @@ initialized above, and dependencies between one complex_vars_() function and another. */ - /* Calls Fmake_range_table(). */ - complex_vars_of_regex (); - /* Calls Fmake_range_table(). */ - complex_vars_of_search (); - - /* Calls make_lisp_hash_table(). */ - complex_vars_of_extents (); - - /* Depends on hash tables and specifiers. */ - complex_vars_of_faces (); - #ifdef MULE /* These two depend on hash tables and various variables declared earlier. The second may also depend on the first. */ complex_vars_of_mule_charset (); #endif -#ifdef FILE_CODING complex_vars_of_file_coding (); +#ifdef HAVE_WIN32_CODING_SYSTEMS + complex_vars_of_intl_win32 (); #endif + /* Calls Fmake_range_table(). */ + complex_vars_of_regex (); + /* Calls Fmake_range_table(). */ + complex_vars_of_search (); + + /* Depends on specifiers. */ + complex_vars_of_faces (); + /* This calls allocate_glyph(), which creates specifiers and also relies on a variable (Vthe_nothing_vector) initialized - above. It also calls make_ext_string(), which under Mule - could require that the charsets be initialized. */ + above. */ complex_vars_of_glyphs (); /* These rely on the glyphs just created in the previous function, @@ -2070,9 +1987,6 @@ stuff. */ complex_vars_of_keymap (); - /* Calls make_lisp_hash_table() and creates a keymap */ - complex_vars_of_event_stream (); - #ifdef ERROR_CHECK_GC { extern int always_gc; @@ -2081,7 +1995,10 @@ } #endif #ifdef PDUMP - } else if (!restart) { /* after successful pdump_load() */ + } + else if (!restart) /* after successful pdump_load() + (note, we are inside ifdef PDUMP) */ + { reinit_alloc_once_early (); reinit_symbols_once_early (); reinit_opaque_once_early (); @@ -2111,16 +2028,23 @@ structure_type_create (); + reinit_coding_system_type_create (); + reinit_coding_system_type_create_unicode (); +#ifdef HAVE_WIN32_CODING_SYSTEMS + reinit_coding_system_type_create_intl_win32 (); +#endif +#ifdef MULE + reinit_coding_system_type_create_mule_coding (); +#endif + structure_type_create_chartab (); structure_type_create_faces (); structure_type_create_rangetab (); structure_type_create_hash_table (); lstream_type_create (); -#ifdef FILE_CODING lstream_type_create_file_coding (); -#endif -#if defined (HAVE_MS_WINDOWS) && !defined(HAVE_MSG_SELECT) +#if defined (HAVE_MS_WINDOWS) && !defined (HAVE_MSG_SELECT) lstream_type_create_mswindows_selectable (); #endif #ifdef HAVE_UNIX_PROCESSES @@ -2152,6 +2076,7 @@ reinit_vars_of_event_stream (); reinit_vars_of_events (); reinit_vars_of_extents (); + reinit_vars_of_file_coding (); reinit_vars_of_fileio (); reinit_vars_of_font_lock (); reinit_vars_of_glyphs (); @@ -2166,7 +2091,9 @@ reinit_vars_of_objects (); reinit_vars_of_print (); reinit_vars_of_search (); + reinit_vars_of_text (); reinit_vars_of_undo (); + reinit_vars_of_unicode (); reinit_vars_of_window (); #ifdef HAVE_MS_WINDOWS @@ -2186,57 +2113,56 @@ reinit_vars_of_menubar_x (); #endif reinit_vars_of_select_x (); -#if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_DIALOGS) || defined (HAVE_TOOLBARS) +#if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_X_DIALOGS) || defined (HAVE_TOOLBARS) reinit_vars_of_gui_x (); #endif #endif /* HAVE_X_WINDOWS */ +#ifdef MULE + reinit_vars_of_mule_coding (); +#endif #if defined (MULE) && defined (HAVE_WNN) reinit_vars_of_mule_wnn (); #endif - reinit_complex_vars_of_buffer (); - reinit_complex_vars_of_console (); + reinit_complex_vars_of_buffer_runtime_only (); + reinit_complex_vars_of_console_runtime_only (); reinit_complex_vars_of_minibuf (); #endif /* PDUMP */ } - /* CONGRATULATIONS!!! We have successfully initialized the Lisp engine. */ if (initialized) - { - /* Stuff that should not be done at dump time, including stuff that - needs to be reset at run time. Order below should not matter. - - Many initializations taken from the environment should go here. */ - reinit_alloc (); - reinit_eval (); -#ifdef MULE_REGEXP - reinit_mule_category (); + init_eval_early (); + +#ifdef MULE + init_mule_charset (); #endif -#ifdef HAVE_POSTGRESQL - init_postgresql_from_environment(); -#endif - } /* Now do further initialization/setup of stuff that is not needed by the syms_of_() routines. This involves stuff that only is enabled in an interactive run (redisplay, user input, etc.) and stuff that is not needed until we start loading Lisp code (the reader). A lot of this stuff involves querying the current environment and needs - to be done both at dump time and at run time. */ - - init_initial_directory(); /* get the directory to use for the - "*scratch*" buffer, etc. */ - -#ifdef WIN32_NATIVE - /* - * For Win32, call init_environment() now, so that environment/registry - * variables will be properly entered into Vprocess_environment. - */ - init_environment(); + to be done both at dump time and at run time. Some will be done + only at run time, by querying the `initialized' variable. */ + +#if defined (WIN32_NATIVE) || defined (CYGWIN) + init_intl_win32 (); /* Under Windows, determine whether we use Unicode + or ANSI to call the system routines -- i.e. + determine what the coding system `mswindows-tstr' + is aliased to */ +#endif + init_buffer_1 (); /* Create *scratch* buffer; init_intl() is going to + call Lisp code (the very first code we call), + and needs a current buffer */ +#ifdef MULE + init_intl (); /* Figure out the locale and set native and + file-name coding systems, initialize the Unicode tables + so that we will be able to process non-ASCII from here + on out! */ #endif init_callproc (); /* Set up the process environment (so that egetenv @@ -2245,13 +2171,26 @@ related to subprocesses. This should be first because many of the functions below call egetenv() to get environment variables. */ + +#ifdef WIN32_NATIVE + /* + * For Win32, call init_environment() to properly enter environment/registry + * variables into Vprocess_environment. + */ + init_environment (); +#endif + + init_initial_directory (); /* get the directory to use for the + "*scratch*" buffer, etc. */ + init_lread (); /* Set up the Lisp reader. */ init_cmdargs (argc, (Extbyte **) argv, skip_args); /* Create list Vcommand_line_args */ - init_buffer (); /* Set default directory of *scratch* buffer */ + init_buffer_2 (); /* Set default directory of *scratch* buffer */ #ifdef WIN32_NATIVE - init_ntproc(); + init_ntproc (); + init_select_mswindows (); #endif init_redisplay (); /* Determine terminal type. @@ -2270,6 +2209,10 @@ #if defined (HAVE_NATIVE_SOUND) && defined (hp9000s800) init_hpplay (); #endif +#ifdef HAVE_POSTGRESQL + /* Set some values taken from environment variables */ + init_postgresql_from_environment (); +#endif #ifdef HAVE_TTY init_device_tty (); #endif @@ -2277,37 +2220,37 @@ /* try to get the actual pathname of the exec file we are running */ if (!restart) - { - Vinvocation_name = Fcar (Vcommand_line_args); - if (XSTRING_DATA(Vinvocation_name)[0] == '-') - { - /* XEmacs as a login shell, oh goody! */ - Vinvocation_name = build_string(getenv("SHELL")); - } - Vinvocation_directory = Vinvocation_name; - - if (!NILP (Ffile_name_directory (Vinvocation_name))) - { - /* invocation-name includes a directory component -- presumably it - is relative to cwd, not $PATH */ - Vinvocation_directory = Fexpand_file_name (Vinvocation_name, - Qnil); - Vinvocation_path = Qnil; - } - else - { - Vinvocation_path = decode_env_path ("PATH", NULL); - locate_file (Vinvocation_path, Vinvocation_name, - Vlisp_EXEC_SUFFIXES, - &Vinvocation_directory, X_OK); - } - - if (NILP (Vinvocation_directory)) + { + Vinvocation_name = Fcar (Vcommand_line_args); + if (XSTRING_DATA(Vinvocation_name)[0] == '-') + { + /* XEmacs as a login shell, oh goody! */ + Vinvocation_name = build_intstring (egetenv ("SHELL")); + } Vinvocation_directory = Vinvocation_name; - Vinvocation_name = Ffile_name_nondirectory (Vinvocation_directory); - Vinvocation_directory = Ffile_name_directory (Vinvocation_directory); - } + if (!NILP (Ffile_name_directory (Vinvocation_name))) + { + /* invocation-name includes a directory component -- presumably it + is relative to cwd, not $PATH */ + Vinvocation_directory = Fexpand_file_name (Vinvocation_name, + Qnil); + Vinvocation_path = Qnil; + } + else + { + Vinvocation_path = split_env_path ("PATH", NULL); + locate_file (Vinvocation_path, Vinvocation_name, + Vlisp_EXEC_SUFFIXES, + &Vinvocation_directory, X_OK); + } + + if (NILP (Vinvocation_directory)) + Vinvocation_directory = Vinvocation_name; + + Vinvocation_name = Ffile_name_nondirectory (Vinvocation_directory); + Vinvocation_directory = Ffile_name_directory (Vinvocation_directory); + } #if defined(HAVE_SHLIB) && !defined(WIN32_NATIVE) /* This is Unix only. MS Windows NT has a library call that does @@ -2320,6 +2263,7 @@ sprintf (buf, "%s/%s", XSTRING_DATA (Vinvocation_directory), XSTRING_DATA (Vinvocation_name)); + C_STRING_TO_EXTERNAL (buf, buf, Qfile_name); /* All we can do is cry if an error happens, so ignore it. */ (void) dll_init (buf); } @@ -2339,12 +2283,8 @@ { /* Handle -l loadup-and-dump, args passed by Makefile. */ if (argc > 2 + skip_args && !strcmp (argv[1 + skip_args], "-l")) + /* !!#### need to be Mule-translating this, but later */ load_me = build_string (argv[2 + skip_args]); -#if 0 /* CANNOT_DUMP - this can never be right in XEmacs --andyp */ - /* Unless next switch is -nl, load "loadup.el" first thing. */ - if (!(argc > 1 + skip_args && !strcmp (argv[1 + skip_args], "-nl"))) - load_me = build_string ("loadup.el"); -#endif /* CANNOT_DUMP */ } #ifdef QUANTIFY @@ -2353,6 +2293,7 @@ #endif /* QUANTIFY */ initialized = 1; + inhibit_non_essential_printing_operations = 0; /* This never returns. */ initial_command_loop (load_me); @@ -2381,6 +2322,9 @@ { "-nd", "--no-dump-file", 95, 0 }, { "-nw", "--no-windows", 90, 0 }, { "-batch", "--batch", 85, 0 }, +#ifdef WIN32_NATIVE + { "-nuni", "--no-unicode-lib-calls", 83, 0 }, +#endif /* WIN32_NATIVE */ { "-debug-paths", "--debug-paths", 82, 0 }, { "-help", "--help", 80, 0 }, { "-version", "--version", 75, 0 }, @@ -2402,6 +2346,7 @@ { "-user", 0, 30, 1 }, { "-debug-init", "--debug-init", 20, 0 }, { "-debug-paths", "--debug-paths", 20, 0 }, + { "-eol", "--enable-eol-detection", 20, 0 }, /* Xt options: */ { "-i", "--icon-type", 15, 0 }, @@ -2644,7 +2589,7 @@ run_temacs_argv [nargs + 1] = 0; catchlist = NULL; /* Important! Otherwise free_cons() calls in condition_case_unwind() may lead to GC death. */ - unbind_to (0, Qnil); /* this closes loadup.el */ + unbind_to (0); /* this closes loadup.el */ purify_flag = 0; run_temacs_argc = nargs + 1; #if defined (HEAP_IN_DATA) && !defined(PDUMP) @@ -2704,6 +2649,7 @@ quantify_clear_data (); #endif /* QUANTIFY */ + inhibit_non_essential_printing_operations = 1; suppress_early_error_handler_backtrace = 0; lim_data = 0; /* force reinitialization of this variable */ @@ -2797,98 +2743,302 @@ } -/* Dumping apparently isn't supported by versions of GCC >= 2.8. */ -/* The following needs conditionalization on whether either XEmacs or */ -/* various system shared libraries have been built and linked with */ -/* GCC >= 2.8. -slb */ -#if defined(GNU_MALLOC) -static void -voodoo_free_hook (void *mem) -{ - /* Disable all calls to free() when XEmacs is exiting and it doesn't */ - /* matter. */ - __free_hook = -#ifdef __GNUC__ /* prototype of __free_hook varies with glibc version */ - (__typeof__ (__free_hook)) +/************************************************************************/ +/* dumping XEmacs (to a new EXE file) */ +/************************************************************************/ + +#ifndef CANNOT_DUMP + +#if !defined(PDUMP) || !defined(SYSTEM_MALLOC) +extern char my_edata[]; #endif - voodoo_free_hook; -} -#endif /* GNU_MALLOC */ - -DEFUN ("kill-emacs", Fkill_emacs, 0, 1, "P", /* -Exit the XEmacs job and kill it. Ask for confirmation, without argument. -If ARG is an integer, return ARG as the exit program code. -If ARG is a string, stuff it as keyboard input. - -The value of `kill-emacs-hook', if not void, -is a list of functions (of no args), -all of which are called before XEmacs is actually killed. + +extern void disable_free_hook (void); + +DEFUN ("dump-emacs", Fdump_emacs, 2, 2, 0, /* +Dump current state of XEmacs into executable file FILENAME. +Take symbols from SYMFILE (presumably the file you executed to run XEmacs). +This is used in the file `loadup.el' when building XEmacs. + +Remember to set `command-line-processed' to nil before dumping +if you want the dumped XEmacs to process its command line +and announce itself normally when it is run. */ - (arg)) + (filename, symfile)) { /* This function can GC */ - struct gcpro gcpro1; - - GCPRO1 (arg); - - if (feof (stdin)) - arg = Qt; - - if (!preparing_for_armageddon && !noninteractive) - run_hook (Qkill_emacs_hook); - - ensure_no_quitting_from_now_on (); - - if (!preparing_for_armageddon) + struct gcpro gcpro1, gcpro2; + int opurify; + + GCPRO2 (filename, symfile); + +#ifdef FREE_CHECKING + Freally_free (Qnil); + + /* When we're dumping, we can't use the debugging free() */ + disable_free_hook (); +#endif + + CHECK_STRING (filename); + filename = Fexpand_file_name (filename, Qnil); + if (!NILP (symfile)) { - Lisp_Object concons, nextcons; - - /* Normally, go ahead and delete all the consoles now. - Some unmentionably lame window systems (MS Wwwww...... eek, - I can't even say it) don't properly clean up after themselves, - and even for those that do, it might be cleaner this way. - If we're going down, however, we don't do this (might - be too dangerous), and if we get a crash somewhere within - this loop, we'll still autosave and won't try this again. */ - - LIST_LOOP_DELETING (concons, nextcons, Vconsole_list) - { - /* There is very little point in deleting the stream console. - It uses stdio, which should flush any buffered output and - something can only go wrong. -slb */ - /* I changed my mind. There's a stupid hack in close to add - a trailing newline. */ - /*if (!CONSOLE_STREAM_P (XCONSOLE (XCAR (concons))))*/ - delete_console_internal (XCONSOLE (XCAR (concons)), 1, 1, 0); - } + CHECK_STRING (symfile); + if (XSTRING_LENGTH (symfile) > 0) + symfile = Fexpand_file_name (symfile, Qnil); + else + symfile = Qnil; } + opurify = purify_flag; + purify_flag = 0; + +#if defined (HEAP_IN_DATA) && !defined(PDUMP) + report_sheap_usage (1); +#endif + + clear_message (); + + fflush (stderr); + fflush (stdout); + + disksave_object_finalization (); + release_breathing_space (); + + /* Tell malloc where start of impure now is */ + /* Also arrange for warnings when nearly out of space. */ +#ifndef SYSTEM_MALLOC + memory_warnings (my_edata, malloc_warning); +#endif + UNGCPRO; + { + Extbyte *filename_ext; + Extbyte *symfile_ext; + + LISP_STRING_TO_EXTERNAL (filename, filename_ext, Qfile_name); + + if (STRINGP (symfile)) + LISP_STRING_TO_EXTERNAL (symfile, symfile_ext, Qfile_name); + else + symfile_ext = 0; + + garbage_collect_1 (); + +#ifdef PDUMP + pdump (); +#else + +#ifdef DOUG_LEA_MALLOC + malloc_state_ptr = malloc_get_state (); +#endif + /* here we break our rule that the filename conversion should + be performed at the actual time that the system call is made. + It's a whole lot easier to do the conversion here than to + modify all the unexec routines to ensure that filename + conversion is applied everywhere. Don't worry about memory + leakage because this call only happens once. */ + unexec (filename_ext, symfile_ext, (uintptr_t) my_edata, 0, 0); +#ifdef DOUG_LEA_MALLOC + free (malloc_state_ptr); +#endif +#endif /* not PDUMP */ + } + + purify_flag = opurify; + + return Qnil; +} + +#endif /* not CANNOT_DUMP */ + + +/************************************************************************/ +/* exiting XEmacs (intended or not) */ +/************************************************************************/ + +/* Ben's capsule summary about expected and unexpected exits from XEmacs. + + Expected exits occur when the user directs XEmacs to exit, for example + by pressing the close button on the only frame in XEmacs, or by typing + C-x C-c. This runs `save-buffers-kill-emacs', which saves any necessary + buffers, and then exits using the primitive `kill-emacs'. + + However, unexpected exits occur in a few different ways: + + -- a memory access violation or other hardware-generated exception + occurs. This is the worst possible problem to deal with, because + the fault can occur while XEmacs is in any state whatsoever, even + quite unstable ones. As a result, we need to be *extremely* careful + what we do. + -- we are using one X display (or if we've used more, we've closed the + others already), and some hardware or other problem happens and + suddenly we've lost our connection to the display. In this situation, + things are not so dire as in the last one; our code itself isn't + trashed, so we can continue execution as normal, after having set + things up so that we can exit at the appropriate time. Our exit + still needs to be of the emergency nature; we have no displays, so + any attempts to use them will fail. We simply want to auto-save + (the single most important thing to do during shut-down), do minimal + cleanup of stuff that has an independent existence outside of XEmacs, + and exit. + + Currently, both unexpected exit scenarios described above set + preparing_for_armageddon to indicate that nonessential and possibly + dangerous things should not be done, specifically: + + -- no garbage collection. + -- no hooks are run. + -- no messages of any sort from autosaving. + -- autosaving tries harder, ignoring certain failures. + -- existing frames are not deleted. + + (Also, all places that set preparing_for_armageddon also + set dont_check_for_quit. This happens separately because it's + also necessary to set other variables to make absolutely sure + no quitting happens.) + + In the first scenario above (the access violation), we also set + fatal_error_in_progress. This causes more things to not happen: + + -- assertion failures do not abort. + -- printing code does not do code conversion or gettext when + printing to stdout/stderr. +*/ + +/* ------------------------------- */ +/* low-level debugging functions */ +/* ------------------------------- */ + +#if defined (WIN32_NATIVE) && defined (DEBUG_XEMACS) +#define debugging_breakpoint() DebugBreak () +#else +#define debugging_breakpoint() +#endif + +void +debug_break (void) +{ + debugging_breakpoint (); +} + +#if defined (WIN32_NATIVE) || defined (CYGWIN) + +/* Return whether all bytes in the specified memory block can be read. */ +int +debug_can_access_memory (void *ptr, Bytecount len) +{ + return !IsBadReadPtr (ptr, len); +} + +#else /* !(defined (WIN32_NATIVE) || defined (CYGWIN)) */ + +/* #### There must be a better way!!!! */ + +static JMP_BUF memory_error_jump; + +static SIGTYPE +debug_memory_error (int signum) +{ + EMACS_REESTABLISH_SIGNAL (signum, debug_memory_error); + EMACS_UNBLOCK_SIGNAL (signum); + LONGJMP (memory_error_jump, 1); +} + +/* Return whether all bytes in the specified memory block can be read. */ +int +debug_can_access_memory (void *ptr, Bytecount len) +{ + /* Use volatile to protect variables from being clobbered by longjmp. */ + SIGTYPE (*volatile old_sigbus) (int); + SIGTYPE (*volatile old_sigsegv) (int); + volatile int old_errno = errno; + volatile int retval = 1; + + if (!SETJMP (memory_error_jump)) + { + old_sigbus = + (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGBUS, debug_memory_error); + old_sigsegv = + (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGSEGV, debug_memory_error); + + if (len > 1) + /* If we can, try to avoid problems with super-optimizing compilers + that might decide that memcmp (ptr, ptr, len) can be optimized + away since its result is always 1. */ + memcmp (ptr, (char *) ptr + 1, len - 1); + else + memcmp (ptr, ptr, len); + } + else + retval = 0; + EMACS_SIGNAL (SIGBUS, old_sigbus); + EMACS_SIGNAL (SIGSEGV, old_sigsegv); + errno = old_errno; + + return retval; +} + +#endif /* defined (WIN32_NATIVE) || defined (CYGWIN) */ + +#ifdef DEBUG_XEMACS + +DEFUN ("force-debugging-signal", Fforce_debugging_signal, 0, 1, 0, /* +Cause XEmacs to enter the debugger. +On some systems, there may be no way to do this gracefully; if so, +nothing happens unless ABORT is non-nil, in which case XEmacs will +abort() -- a sure-fire way to immediately get back to the debugger, +but also a sure-fire way to kill XEmacs (and dump core on Unix +systems)! +*/ + (abort_)) +{ + debugging_breakpoint (); + if (!NILP (abort_)) + abort (); + return Qnil; +} + +#endif /* DEBUG_XEMACS */ + +/* ------------------------------- */ +/* some helper functions */ +/* ------------------------------- */ + +static void +ensure_no_quitting_from_now_on (void) +{ + /* make sure no quitting from now on!! */ + dont_check_for_quit = 1; + Vinhibit_quit = Qt; + Vquit_flag = Qnil; +} + #ifdef HAVE_MS_WINDOWS +static void +pause_so_user_can_read_messages (int allow_further) +{ + static int already_paused; + + if (already_paused) + return; + if (!allow_further) + already_paused = 1; /* If we displayed a message on the console, then we must allow the user to see this message. This may be unnecessary, but can't hurt, and we can't necessarily check arg; e.g. xemacs --help kills with argument 0. */ if (mswindows_message_outputted) - Fmswindows_message_box (build_string ("Messages outputted. XEmacs is exiting."), - Qnil, Qnil); + Fmswindows_message_box + (build_msg_string ("Messages outputted. XEmacs is exiting."), + Qnil, Qnil); +} #endif - shut_down_emacs (0, STRINGP (arg) ? arg : Qnil, 0); - -#if defined(GNU_MALLOC) - __free_hook = -#ifdef __GNUC__ /* prototype of __free_hook varies with glibc version */ - (__typeof__ (__free_hook)) -#endif - voodoo_free_hook; -#endif - - exit (INTP (arg) ? XINT (arg) : 0); - /* NOTREACHED */ - return Qnil; /* I'm sick of the compiler warning */ -} +/* -------------------------------- */ +/* a (more-or-less) normal shutdown */ +/* -------------------------------- */ /* Perform an orderly shutdown of XEmacs. Autosave any modified buffers, kill any child processes, clean up the terminal modes (if @@ -2901,6 +3051,7 @@ This is called by fatal signal handlers and Fkill_emacs. It used to be called by X protocol error handlers, but instead they now call Fkill_emacs. */ + static void shut_down_emacs (int sig, Lisp_Object stuff, int no_auto_save) { @@ -3021,227 +3172,255 @@ tt_close (); #endif #endif /* TOOLTALK */ - } - -#ifndef CANNOT_DUMP - -#if !defined(PDUMP) || !defined(SYSTEM_MALLOC) -extern char my_edata[]; +/* Dumping apparently isn't supported by versions of GCC >= 2.8. */ +/* The following needs conditionalization on whether either XEmacs or */ +/* various system shared libraries have been built and linked with */ +/* GCC >= 2.8. -slb */ +#if defined(GNU_MALLOC) +static void +voodoo_free_hook (void *mem) +{ + /* Disable all calls to free() when XEmacs is exiting and it doesn't */ + /* matter. */ + __free_hook = +#ifdef __GNUC__ /* prototype of __free_hook varies with glibc version */ + (__typeof__ (__free_hook)) #endif - -extern void disable_free_hook (void); - -DEFUN ("dump-emacs", Fdump_emacs, 2, 2, 0, /* -Dump current state of XEmacs into executable file FILENAME. -Take symbols from SYMFILE (presumably the file you executed to run XEmacs). -This is used in the file `loadup.el' when building XEmacs. - -Remember to set `command-line-processed' to nil before dumping -if you want the dumped XEmacs to process its command line -and announce itself normally when it is run. + voodoo_free_hook; +} +#endif /* GNU_MALLOC */ + +DEFUN ("kill-emacs", Fkill_emacs, 0, 1, "P", /* +Exit the XEmacs job and kill it. Ask for confirmation, without argument. +If ARG is an integer, return ARG as the exit program code. +If ARG is a string, stuff it as keyboard input. + +The value of `kill-emacs-hook', if not void, +is a list of functions (of no args), +all of which are called before XEmacs is actually killed. */ - (filename, symfile)) + (arg)) { /* This function can GC */ - struct gcpro gcpro1, gcpro2; - int opurify; - - GCPRO2 (filename, symfile); - -#ifdef FREE_CHECKING - Freally_free (Qnil); - - /* When we're dumping, we can't use the debugging free() */ - disable_free_hook (); -#endif - - CHECK_STRING (filename); - filename = Fexpand_file_name (filename, Qnil); - if (!NILP (symfile)) + struct gcpro gcpro1; + + GCPRO1 (arg); + + if (feof (stdin)) + arg = Qt; + + if (!preparing_for_armageddon && !noninteractive) + run_hook (Qkill_emacs_hook); + + ensure_no_quitting_from_now_on (); + + if (!preparing_for_armageddon) { - CHECK_STRING (symfile); - if (XSTRING_LENGTH (symfile) > 0) - symfile = Fexpand_file_name (symfile, Qnil); - else - symfile = Qnil; + Lisp_Object concons, nextcons; + + /* Normally, go ahead and delete all the consoles now. + Some unmentionably lame window systems (MS Wwwww...... eek, + I can't even say it) don't properly clean up after themselves, + and even for those that do, it might be cleaner this way. + If we're going down, however, we don't do this (might + be too dangerous), and if we get a crash somewhere within + this loop, we'll still autosave and won't try this again. */ + + LIST_LOOP_DELETING (concons, nextcons, Vconsole_list) + { + /* There is very little point in deleting the stream console. + It uses stdio, which should flush any buffered output and + something can only go wrong. -slb */ + /* I changed my mind. There's a stupid hack in close to add + a trailing newline. */ + /*if (!CONSOLE_STREAM_P (XCONSOLE (XCAR (concons))))*/ + delete_console_internal (XCONSOLE (XCAR (concons)), 1, 1, 0); + } } - opurify = purify_flag; - purify_flag = 0; - -#if defined (HEAP_IN_DATA) && !defined(PDUMP) - report_sheap_usage (1); -#endif - - clear_message (); - - fflush (stderr); - fflush (stdout); - - disksave_object_finalization (); - release_breathing_space (); - - /* Tell malloc where start of impure now is */ - /* Also arrange for warnings when nearly out of space. */ -#ifndef SYSTEM_MALLOC - memory_warnings (my_edata, malloc_warning); -#endif - UNGCPRO; - { - char *filename_ext; - char *symfile_ext; - - LISP_STRING_TO_EXTERNAL (filename, filename_ext, Qfile_name); - - if (STRINGP (symfile)) - LISP_STRING_TO_EXTERNAL (symfile, symfile_ext, Qfile_name); - else - symfile_ext = 0; - - garbage_collect_1 (); - -#ifdef PDUMP - pdump (); -#else - -#ifdef DOUG_LEA_MALLOC - malloc_state_ptr = malloc_get_state (); +#ifdef HAVE_MS_WINDOWS + pause_so_user_can_read_messages (1); #endif - /* here we break our rule that the filename conversion should - be performed at the actual time that the system call is made. - It's a whole lot easier to do the conversion here than to - modify all the unexec routines to ensure that filename - conversion is applied everywhere. Don't worry about memory - leakage because this call only happens once. */ - unexec (filename_ext, symfile_ext, (uintptr_t) my_edata, 0, 0); -#ifdef DOUG_LEA_MALLOC - free (malloc_state_ptr); + + shut_down_emacs (0, STRINGP (arg) ? arg : Qnil, 0); + +#if defined(GNU_MALLOC) + __free_hook = +#ifdef __GNUC__ /* prototype of __free_hook varies with glibc version */ + (__typeof__ (__free_hook)) +#endif + voodoo_free_hook; #endif -#endif /* not PDUMP */ - } - - purify_flag = opurify; - - return Qnil; + + exit (INTP (arg) ? XINT (arg) : 0); + /* NOTREACHED */ + return Qnil; /* I'm sick of the compiler warning */ } -#endif /* not CANNOT_DUMP */ - - -/* Split STRING into a list of substrings. The substrings are the - parts of original STRING separated by SEPCHAR. */ -static Lisp_Object -split_string_by_emchar_1 (const Intbyte *string, Bytecount size, - Emchar sepchar) +/* -------------------------------- */ +/* abnormal shutdowns: GP faults */ +/* -------------------------------- */ + +/* Handle bus errors, illegal instruction, etc: actual implementation. */ +static void +guts_of_fatal_error_signal (int sig) { - Lisp_Object result = Qnil; - const Intbyte *end = string + size; - - while (1) + fatal_error_in_progress++; + inhibit_non_essential_printing_operations = 1; + preparing_for_armageddon = 1; + + ensure_no_quitting_from_now_on (); + + /* Only try auto-saving first time through. If we crash in auto-saving, + don't do it again. */ + if (fatal_error_in_progress == 1) { - const Intbyte *p = string; - while (p < end) - { - if (charptr_emchar (p) == sepchar) - break; - INC_CHARPTR (p); - } - result = Fcons (make_string (string, p - string), result); - if (p < end) - { - string = p; - INC_CHARPTR (string); /* skip sepchar */ - } - else - break; + Fdo_auto_save (Qt, Qnil); /* do this before anything hazardous */ + /* Do this so that the variable has the same value of 2 regardless of + whether we made it through auto-saving correctly. */ + fatal_error_in_progress++; } - return Fnreverse (result); + else if (fatal_error_in_progress == 2) + stderr_out ("WARNING: Unable to auto-save your files properly.\n" + "Some or all may in fact have been auto-saved.\n" + "\n"); + + /* Now, reset our signal handler, so the next time, we just die. + Don't do this before auto-saving. */ + if (sig >= 0) + EMACS_SIGNAL (sig, SIG_DFL); + + /* Keep in mind that there's more than one signal that we can crash + on. */ + /* If fatal error occurs in code below, avoid infinite recursion. */ + if (fatal_error_in_progress <= 2) + { + shut_down_emacs (sig, Qnil, 1); + stderr_out ("\nLisp backtrace follows:\n\n"); + debug_backtrace (); +# if 0 /* This is evil, rarely useful, and causes grief in some cases. */ + /* Check for Sun-style stack printing via /proc */ + { + const Char_ASCII *pstack = "/usr/proc/bin/pstack"; + if (access (pstack, X_OK) == 0) + { + Char_ASCII buf[100]; + stderr_out ("\nC backtrace follows:\n" + "(A real debugger may provide better information)\n\n"); + sprintf (buf, "%s %d >&2", pstack, (int)getpid()); + system (buf); + } + } +# endif +#ifdef HAVE_MS_WINDOWS + pause_so_user_can_read_messages (0); +#endif + } } -/* The same as the above, except PATH is an external C string (it is - converted using Qfile_name), and sepchar is hardcoded to SEPCHAR - (':' or whatever). */ -Lisp_Object -decode_path (const char *path) +/* This is called when a fatal signal (SIGBUS aka "bus error", SIGSEGV aka + "segmentation violation", SIGILL aka "illegal instruction", and many + others) is sent to the program. This generally happens under Unix, + not MS Windows. */ +SIGTYPE +fatal_error_signal (int sig) { - Bytecount newlen; - Intbyte *newpath; - if (!path) - return Qnil; - - TO_INTERNAL_FORMAT (C_STRING, path, ALLOCA, (newpath, newlen), Qfile_name); - - /* #### Does this make sense? It certainly does for - decode_env_path(), but it looks dubious here. Does any code - depend on decode_path("") returning nil instead of an empty - string? */ - if (!newlen) - return Qnil; - - return split_string_by_emchar_1 (newpath, newlen, SEPCHAR); + /* Unblock the signal so that if the same signal gets sent in the + code below, we avoid a deadlock. */ + EMACS_UNBLOCK_SIGNAL (sig); + + guts_of_fatal_error_signal (sig); + + /* Signal the same code; this time it will really be fatal. */ +#ifdef WIN32_NATIVE + raise (sig); +#else + kill (qxe_getpid (), sig); +#endif + SIGRETURN; } -Lisp_Object -decode_env_path (const char *evarname, const char *default_) +#ifdef _MSC_VER + +#define STATUS_ASSERTION_FAILURE 0xE0000001 + +static DWORD +mswindows_handle_hardware_exceptions_1 (void) { - const char *path = 0; - if (evarname) - path = egetenv (evarname); - if (!path) - path = default_; - return decode_path (path); + pause_so_user_can_read_messages (0); + return EXCEPTION_EXECUTE_HANDLER; } -/* Ben thinks this function should not exist or be exported to Lisp. - We use it to define split-path-string in subr.el (not!). */ - -DEFUN ("split-string-by-char", Fsplit_string_by_char, 1, 2, 0, /* -Split STRING into a list of substrings originally separated by SEPCHAR. -*/ - (string, sepchar)) +/* This is called under MS Windows when an exception (this encompasses both + user-defined exceptions and hardware exceptions such as GP faults aka + SIGBUS or SIGSEGV) is triggered. */ + +static DWORD +mswindows_handle_hardware_exceptions (DWORD code) { - CHECK_STRING (string); - CHECK_CHAR (sepchar); - return split_string_by_emchar_1 (XSTRING_DATA (string), - XSTRING_LENGTH (string), - XCHAR (sepchar)); + if (code != STATUS_ACCESS_VIOLATION && code != STATUS_ILLEGAL_INSTRUCTION + && code != STATUS_PRIVILEGED_INSTRUCTION + && code != STATUS_DATATYPE_MISALIGNMENT + && code != STATUS_ASSERTION_FAILURE) + return EXCEPTION_CONTINUE_SEARCH; + + /* I don't know if this filter is still wrapped in the outer __try, but + it doesn't hurt to have another one, and it lets us control more + exactly what we really want to do in such a situation. What we do is + pause, if we haven't already done so, so that the user can see what's + output. This is critical because otherwise the output is gone. */ + __try + { + guts_of_fatal_error_signal (-1); + } + /* VC++ documentation says that + GetExceptionCode() cannot be called inside the filter itself. */ + + /* __except (mswindows_handle_hardware_exceptions (GetExceptionCode ())) {} + + The line above is original. Unfortunately, when an error is tripped + inside of the handler (e.g. during Fbacktrace()), and the handler for + the handler is invoked, it correctly notices that something is amiss + and it should just return -- but it returns EXCEPTION_CONTINUE_SEARCH, + which causes the debugger to be invoked debugging the handler code in + this function -- and WITH THE STACK UNWOUND so that you see main() + calling mswindows_handle_hardware_exceptions(), calling Fbacktrace(), + and a crash a couple of frames in -- AND NO SIGN OF THE ORIGINAL CRASH! + + There's some real weirdness going on in the stack handling -- unlike + in Unix, where further crashes just keep adding to the stack, it seems + that under the structured-exception-handling, the stack can actually + bounce back and forth between the full stack at the location of the + exception and the unwound stack at the place where the __try clause was + established. I don't completely understand it. What I do know is that + returning EXCEPTION_EXECUTE_HANDLER on nested crash has the effect of + aborting execution of the handler and going back to the outer filter + function, which returns EXCEPTION_CONTINUE_SEARCH and everything is + hunky-dorey -- your debugger sees a crash at the right location with + the right stack. + + I'm leaving in the trickier Unix-like code in the handler; someone who + understands better than me how the stack works in these handlers could + fix it up more. As it is, it works pretty well, so I'm not likely to + touch it more. --ben + */ + + __except (mswindows_handle_hardware_exceptions_1 ()) {} + + /* pretend we didn't handle this, so that the debugger is invoked and/or + the normal GPF box appears. */ + return EXCEPTION_CONTINUE_SEARCH; } -/* #### This was supposed to be in subr.el, but is used VERY early in - the bootstrap process, so it goes here. Damn. */ - -DEFUN ("split-path", Fsplit_path, 1, 1, 0, /* -Explode a search path into a list of strings. -The path components are separated with the characters specified -with `path-separator'. -*/ - (path)) -{ - CHECK_STRING (path); - - while (!STRINGP (Vpath_separator) - || (XSTRING_CHAR_LENGTH (Vpath_separator) != 1)) - Vpath_separator = signal_continuable_error - (Qinvalid_state, - "`path-separator' should be set to a single-character string", - Vpath_separator); - - return (split_string_by_emchar_1 - (XSTRING_DATA (path), XSTRING_LENGTH (path), - charptr_emchar (XSTRING_DATA (Vpath_separator)))); -} - -DEFUN ("noninteractive", Fnoninteractive, 0, 0, 0, /* -Non-nil return value means XEmacs is running without interactive terminal. -*/ - ()) -{ - return noninteractive ? Qt : Qnil; -} +#endif /* _MSC_VER */ + +/* -------------------------------------- */ +/* abnormal shutdowns: assertion failures */ +/* -------------------------------------- */ /* This flag is useful to define if you're under a debugger; this way, you can put a breakpoint of assert_failed() and debug multiple problems @@ -3251,7 +3430,10 @@ #ifdef USE_ASSERTIONS /* This highly dubious kludge ... shut up Jamie, I'm tired of your slagging. */ +/* Nonzero if handling an assertion failure. (Bumped by one each time + we recursively hit such a failure.) */ static int in_assert_failed; + static const char *assert_failed_file; static int assert_failed_line; static const char *assert_failed_expr; @@ -3260,14 +3442,9 @@ #undef fprintf #endif -#undef abort /* avoid infinite #define loop... */ - -#if defined (WIN32_NATIVE) && defined (DEBUG_XEMACS) -#define enter_debugger() DebugBreak () -#else -#define enter_debugger() -#endif - +/* This is called when an assert() fails or when abort() is called -- both + of those are defined in the preprocessor to an expansion involving + assert_failed(). */ void assert_failed (const char *file, int line, const char *expr) { @@ -3279,19 +3456,21 @@ /* We are extremely paranoid so we sensibly deal with recursive assertion failures. */ in_assert_failed++; + inhibit_non_essential_printing_operations = 1; if (in_assert_failed >= 4) _exit (-1); else if (in_assert_failed == 3) { - enter_debugger (); + debugging_breakpoint (); _exit (-1); } else if (in_assert_failed == 2) { - /* Not stderr_out(), which does additional things and may trigger - a recursive assertion failure. fprintf was undeffed above, in - case it was encapsulated. */ + /* Ultra-paranoia. stderr_out() tries very hard not to do + anything during assertion failures that might trigger more + failures; but we might have messed up somewhere. fprintf was + undeffed above, in case it was encapsulated. */ fprintf (stderr, "Fatal error: recursive assertion failure, " "file %s, line %d, %s\n", @@ -3306,44 +3485,83 @@ assert_failed_line = line; assert_failed_expr = expr; - if (!initialized) - fprintf (stderr, - "Fatal error: assertion failed, file %s, line %d, %s\n", - file, line, expr); - else - stderr_out ("Fatal error: assertion failed, file %s, line %d, %s\n", - file, line, expr); + stderr_out ("\nFatal error: assertion failed, file %s, line %d, %s\n", + file, line, expr); } - enter_debugger (); + /* Enable the following if you want a breakpoint right away to the + debugger, without the whole shutdown processing first. This can be + useful if you're afraid the shutdown processing will modify state that + you're trying to debug (generally fairly unlikely); but you then don't + get the auto-save behavior, which may be extremely important if you + were in the middle of doing something */ + /* debugging_breakpoint (); */ #if !defined (ASSERTIONS_DONT_ABORT) - abort (); -#endif +#ifdef _MSC_VER + /* Calling abort() directly just seems to exit, in a way we can't + trap. (#### The docs say it does raise(SIGABRT), which we should be + able to trap. Perhaps we're messing up somewhere? Or perhaps MS is + messed up.) + + So, instead we cause an exception and enter into the structured + exception-handling mechanism, which is just like what happens when a + GPF occurs, and is cleaner anyway. (If we entered into one of the + signal handlers, a crash in there would enter anyway into the + structured exception stuff, and you'd get some weird mixture. Cleaner + to keep it all in the expected way.) + */ + /* Either of the following work in terms of causing an exception. The + second one looks cleaner but you get an odd message about "Unknown + software exception ..." without the obvious "OK to terminate", "Cancel + to debug"; instead, you just get OK/Cancel, which in fact do those + same things. */ + * ((int *) 0) = 666; + /* RaiseException (STATUS_ASSERTION_FAILURE, EXCEPTION_NONCONTINUABLE, 0, + 0); */ +#else + really_abort (); +#endif /* _MSC_VER */ +#endif /* !defined (ASSERTIONS_DONT_ABORT) */ + inhibit_non_essential_printing_operations = 0; in_assert_failed = 0; } #endif /* USE_ASSERTIONS */ - -#ifdef DEBUG_XEMACS - -DEFUN ("force-debugging-signal", Fforce_debugging_signal, 0, 1, 0, /* -Cause XEmacs to enter the debugger. -On some systems, there may be no way to do this gracefully; if so, -nothing happens unless ABORT is non-nil, in which case XEmacs will -abort() -- a sure-fire way to immediately get back to the debugger, -but also a sure-fire way to kill XEmacs (and dump core on Unix -systems)! +/* -------------------------------------- */ +/* low-memory notification */ +/* -------------------------------------- */ + +#ifdef SIGDANGER + +/* Handler for SIGDANGER. */ +SIGTYPE +memory_warning_signal (int sig) +{ + /* #### bad bad bad; this function shouldn't do anything except + set a flag, or weird corruption could happen. */ + EMACS_SIGNAL (sig, memory_warning_signal); + + malloc_warning + (GETTEXT ("Operating system warns that virtual memory is running low.\n")); + + /* It might be unsafe to call do_auto_save now. */ + force_auto_save_soon (); +} +#endif /* SIGDANGER */ + + +/************************************************************************/ +/* Miscellaneous */ +/************************************************************************/ + +DEFUN ("noninteractive", Fnoninteractive, 0, 0, 0, /* +Non-nil return value means XEmacs is running without interactive terminal. */ - (abort_)) + ()) { - enter_debugger (); - if (!NILP (abort_)) - abort (); - return Qnil; + return noninteractive ? Qt : Qnil; } -#endif /* DEBUG_XEMACS */ - #ifdef QUANTIFY DEFUN ("quantify-start-recording-data", Fquantify_start_recording_data, 0, 0, "", /* @@ -3399,9 +3617,6 @@ DEFSUBR (Fquantify_clear_data); #endif /* QUANTIFY */ - DEFSUBR (Fsplit_string_by_char); - DEFSUBR (Fsplit_path); /* #### */ - DEFSYMBOL (Qkill_emacs_hook); DEFSYMBOL (Qsave_buffers_kill_emacs); } @@ -3446,7 +3661,7 @@ Symbol indicating type of operating system you are using. */ ); Vsystem_type = intern (SYSTEM_TYPE); - Fprovide (intern(SYSTEM_TYPE)); + Fprovide (Vsystem_type); #ifndef EMACS_CONFIGURATION # define EMACS_CONFIGURATION "UNKNOWN" @@ -3642,25 +3857,17 @@ */ ); { #if defined(MAIL_LOCK_FLOCK) && defined(HAVE_FLOCK) - Vconfigure_mail_lock_method = intern("flock"); + Vconfigure_mail_lock_method = intern ("flock"); #elif defined(MAIL_LOCK_LOCKF) && defined(HAVE_LOCKF) - Vconfigure_mail_lock_method = intern("lockf"); + Vconfigure_mail_lock_method = intern ("lockf"); #elif defined(MAIL_LOCK_MMDF) && defined(HAVE_MMDF) - Vconfigure_mail_lock_method = intern("mmdf"); + Vconfigure_mail_lock_method = intern ("mmdf"); #elif defined(MAIL_LOCK_LOCKING) && defined(HAVE_LOCKING) - Vconfigure_mail_lock_method = intern("locking"); + Vconfigure_mail_lock_method = intern ("locking"); #else - Vconfigure_mail_lock_method = intern("dot"); + Vconfigure_mail_lock_method = intern ("dot"); #endif } - - DEFVAR_LISP ("path-separator", &Vpath_separator /* -The directory separator in search paths, as a string. -*/ ); - { - char c = SEPCHAR; - Vpath_separator = make_string ((Intbyte *)&c, 1); - } } void @@ -3673,14 +3880,14 @@ For example, this may be \"xemacs\" or \"infodock\". This is mainly meant for use in path searching. */ ); - Vemacs_program_name = build_string ((char *) PATH_PROGNAME); + Vemacs_program_name = build_ext_string (PATH_PROGNAME, Qfile_name); DEFVAR_LISP ("emacs-program-version", &Vemacs_program_version /* *Version of the Emacs variant. This typically has the form NN.NN-bNN. This is mainly meant for use in path searching. */ ); - Vemacs_program_version = build_string ((char *) PATH_VERSION); + Vemacs_program_version = build_ext_string (PATH_VERSION, Qfile_name); DEFVAR_LISP ("exec-path", &Vexec_path /* *List of directories to search programs to run in subprocesses. @@ -3700,7 +3907,7 @@ */ ); #ifdef PATH_EXEC Vconfigure_exec_directory = Ffile_name_as_directory - (build_string ((char *) PATH_EXEC)); + (build_ext_string (PATH_EXEC, Qfile_name)); #else Vconfigure_exec_directory = Qnil; #endif @@ -3716,7 +3923,7 @@ */ ); #ifdef PATH_LOADSEARCH Vconfigure_lisp_directory = Ffile_name_as_directory - (build_string ((char *) PATH_LOADSEARCH)); + (build_ext_string (PATH_LOADSEARCH, Qfile_name)); #else Vconfigure_lisp_directory = Qnil; #endif @@ -3748,7 +3955,7 @@ */ ); #ifdef PATH_MODULESEARCH Vconfigure_module_directory = Ffile_name_as_directory - (build_string ((char *) PATH_MODULESEARCH)); + (build_ext_string (PATH_MODULESEARCH, Qfile_name)); #else Vconfigure_module_directory = Qnil; #endif @@ -3758,7 +3965,7 @@ configure's idea of what the package path will be. */ ); #ifdef PATH_PACKAGEPATH - Vconfigure_package_path = decode_path (PATH_PACKAGEPATH); + Vconfigure_package_path = split_external_path (PATH_PACKAGEPATH); #else Vconfigure_package_path = Qnil; #endif @@ -3778,7 +3985,7 @@ */ ); #ifdef PATH_DATA Vconfigure_data_directory = Ffile_name_as_directory - (build_string ((char *) PATH_DATA)); + (build_ext_string (PATH_DATA, Qfile_name)); #else Vconfigure_data_directory = Qnil; #endif @@ -3800,7 +4007,7 @@ */ ); #ifdef PATH_SITE Vconfigure_site_directory = Ffile_name_as_directory - (build_string ((char *) PATH_SITE)); + (build_ext_string (PATH_SITE, Qfile_name)); #else Vconfigure_site_directory = Qnil; #endif @@ -3816,7 +4023,7 @@ */ ); #ifdef PATH_SITE_MODULES Vconfigure_site_module_directory = Ffile_name_as_directory - (build_string ((char *) PATH_SITE_MODULES)); + (build_ext_string (PATH_SITE_MODULES, Qfile_name)); #else Vconfigure_site_module_directory = Qnil; #endif @@ -3833,7 +4040,7 @@ */ ); #ifdef PATH_DOC Vconfigure_doc_directory = Ffile_name_as_directory - (build_string ((char *) PATH_DOC)); + (build_ext_string (PATH_DOC, Qfile_name)); #else Vconfigure_doc_directory = Qnil; #endif @@ -3844,7 +4051,7 @@ */ ); #ifdef PATH_EXEC_PREFIX Vconfigure_exec_prefix_directory = Ffile_name_as_directory - (build_string ((char *) PATH_EXEC_PREFIX)); + (build_ext_string (PATH_EXEC_PREFIX, Qfile_name)); #else Vconfigure_exec_prefix_directory = Qnil; #endif @@ -3855,7 +4062,7 @@ */ ); #ifdef PATH_PREFIX Vconfigure_prefix_directory = Ffile_name_as_directory - (build_string ((char *) PATH_PREFIX)); + (build_ext_string (PATH_PREFIX, Qfile_name)); #else Vconfigure_prefix_directory = Qnil; #endif @@ -3868,7 +4075,7 @@ */ ); #ifdef PATH_INFO Vconfigure_info_directory = - Ffile_name_as_directory (build_string (PATH_INFO)); + Ffile_name_as_directory (build_ext_string (PATH_INFO, Qfile_name)); #else Vconfigure_info_directory = Qnil; #endif @@ -3877,7 +4084,7 @@ The configured initial path for info documentation. */ ); #ifdef PATH_INFOPATH - Vconfigure_info_path = decode_path (PATH_INFOPATH); + Vconfigure_info_path = split_external_path (PATH_INFOPATH); #else Vconfigure_info_path = Qnil; #endif @@ -3897,3 +4104,13 @@ } #endif + +#undef abort /* Get access to the real version of abort. We put this all + the way at the end to make sure that all calls to abort() + anywhere in the above code go through assert_failed(). */ + +void +really_abort (void) +{ + abort (); +}