use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / emacs.c
index ac9f79b..bef3266 100644 (file)
@@ -1,7 +1,7 @@
 /* Fully extensible Emacs, running on Unix, intended for GNU.
 
 /* Fully extensible Emacs, running on Unix, intended for GNU.
 
-Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2014 Free Software
-Foundation, Inc.
+Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2014
+  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -27,6 +27,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/types.h>
 #include <sys/file.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/file.h>
 #include <unistd.h>
+#include <libguile.h>
 
 #include <close-stream.h>
 
 
 #include <close-stream.h>
 
@@ -80,6 +81,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "composite.h"
 #include "dispextern.h"
 #include "syntax.h"
 #include "composite.h"
 #include "dispextern.h"
 #include "syntax.h"
+#include "sysselect.h"
 #include "systime.h"
 
 #ifdef HAVE_GNUTLS
 #include "systime.h"
 
 #ifdef HAVE_GNUTLS
@@ -105,8 +107,9 @@ extern void moncontrol (int mode);
 #include <sys/personality.h>
 #endif
 
 #include <sys/personality.h>
 #endif
 
-static const char emacs_version[] = VERSION;
+static const char emacs_version[] = PACKAGE_VERSION;
 static const char emacs_copyright[] = COPYRIGHT;
 static const char emacs_copyright[] = COPYRIGHT;
+static const char emacs_bugreport[] = PACKAGE_BUGREPORT;
 
 /* Empty lisp strings.  To avoid having to build any others.  */
 Lisp_Object empty_unibyte_string, empty_multibyte_string;
 
 /* Empty lisp strings.  To avoid having to build any others.  */
 Lisp_Object empty_unibyte_string, empty_multibyte_string;
@@ -121,6 +124,9 @@ Lisp_Object Vlibrary_cache;
    on subsequent starts.  */
 bool initialized;
 
    on subsequent starts.  */
 bool initialized;
 
+/* Set to true if this instance of Emacs might dump.  */
+bool might_dump;
+
 #ifdef DARWIN_OS
 extern void unexec_init_emacs_zone (void);
 #endif
 #ifdef DARWIN_OS
 extern void unexec_init_emacs_zone (void);
 #endif
@@ -132,7 +138,7 @@ static void *malloc_state_ptr;
 /* From glibc, a routine that returns a copy of the malloc internal state.  */
 extern void *malloc_get_state (void);
 /* From glibc, a routine that overwrites the malloc internal state.  */
 /* From glibc, a routine that returns a copy of the malloc internal state.  */
 extern void *malloc_get_state (void);
 /* From glibc, a routine that overwrites the malloc internal state.  */
-extern int malloc_set_state (void*);
+extern int malloc_set_state (void *);
 /* True if the MALLOC_CHECK_ environment variable was set while
    dumping.  Used to work around a bug in glibc's malloc.  */
 static bool malloc_using_checking;
 /* True if the MALLOC_CHECK_ environment variable was set while
    dumping.  Used to work around a bug in glibc's malloc.  */
 static bool malloc_using_checking;
@@ -160,10 +166,6 @@ bool running_asynch_code;
 bool display_arg;
 #endif
 
 bool display_arg;
 #endif
 
-/* An address near the bottom of the stack.
-   Tells GC how to save a copy of the stack.  */
-char *stack_bottom;
-
 #if defined (DOUG_LEA_MALLOC) || defined (GNU_LINUX)
 /* The address where the heap starts (from the first sbrk (0) call).  */
 static void *my_heap_start;
 #if defined (DOUG_LEA_MALLOC) || defined (GNU_LINUX)
 /* The address where the heap starts (from the first sbrk (0) call).  */
 static void *my_heap_start;
@@ -210,7 +212,7 @@ int initial_argc;
 static void sort_args (int argc, char **argv);
 static void syms_of_emacs (void);
 
 static void sort_args (int argc, char **argv);
 static void syms_of_emacs (void);
 
-/* C89 needs each string be at most 509 characters, so the usage
+/* C99 needs each string to be at most 4095 characters, and the usage
    strings below are split to not overflow this limit.  */
 static char const *const usage_message[] =
   { "\
    strings below are split to not overflow this limit.  */
 static char const *const usage_message[] =
   { "\
@@ -321,7 +323,7 @@ abbreviation for a --option.\n\
 Various environment variables and window system resources also affect\n\
 the operation of Emacs.  See the main documentation.\n\
 \n\
 Various environment variables and window system resources also affect\n\
 the operation of Emacs.  See the main documentation.\n\
 \n\
-Report bugs to bug-gnu-emacs@gnu.org.  First, please see the Bugs\n\
+Report bugs to " PACKAGE_BUGREPORT ".  First, please see the Bugs\n\
 section of the Emacs manual or the file BUGS.\n"
   };
 
 section of the Emacs manual or the file BUGS.\n"
   };
 
@@ -388,7 +390,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd)
 {
   register int i;
   Lisp_Object name, dir, handler;
 {
   register int i;
   Lisp_Object name, dir, handler;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
   Lisp_Object raw_name;
 
   initial_argv = argv;
   Lisp_Object raw_name;
 
   initial_argv = argv;
@@ -547,7 +549,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd)
          = Fcons (build_unibyte_string (argv[i]), Vcommand_line_args);
     }
 
          = Fcons (build_unibyte_string (argv[i]), Vcommand_line_args);
     }
 
-  unbind_to (count, Qnil);
+  dynwind_end ();
 }
 
 DEFUN ("invocation-name", Finvocation_name, Sinvocation_name, 0, 0, 0,
 }
 
 DEFUN ("invocation-name", Finvocation_name, Sinvocation_name, 0, 0, 0,
@@ -665,9 +667,7 @@ malloc_initialize_hook (void)
        }
 
       malloc_set_state (malloc_state_ptr);
        }
 
       malloc_set_state (malloc_state_ptr);
-#ifndef XMALLOC_OVERRUN_CHECK
       free (malloc_state_ptr);
       free (malloc_state_ptr);
-#endif
     }
   else
     {
     }
   else
     {
@@ -700,10 +700,6 @@ close_output_streams (void)
 int
 main (int argc, char **argv)
 {
 int
 main (int argc, char **argv)
 {
-#if GC_MARK_STACK
-  Lisp_Object dummy;
-#endif
-  char stack_bottom_variable;
   bool do_initial_setlocale;
   bool dumping;
   int skip_args = 0;
   bool do_initial_setlocale;
   bool dumping;
   int skip_args = 0;
@@ -721,16 +717,16 @@ main (int argc, char **argv)
   /* If we use --chdir, this records the original directory.  */
   char *original_pwd = 0;
 
   /* If we use --chdir, this records the original directory.  */
   char *original_pwd = 0;
 
-#if GC_MARK_STACK
-  stack_base = &dummy;
-#endif
-
 #ifdef G_SLICE_ALWAYS_MALLOC
   /* This is used by the Cygwin build.  It's not needed starting with
      cygwin-1.7.24, but it doesn't do any harm.  */
   xputenv ("G_SLICE=always-malloc");
 #endif
 
 #ifdef G_SLICE_ALWAYS_MALLOC
   /* This is used by the Cygwin build.  It's not needed starting with
      cygwin-1.7.24, but it doesn't do any harm.  */
   xputenv ("G_SLICE=always-malloc");
 #endif
 
+#ifndef CANNOT_DUMP
+  might_dump = !initialized;
+#endif
+
 #ifdef GNU_LINUX
   if (!initialized)
     {
 #ifdef GNU_LINUX
   if (!initialized)
     {
@@ -749,6 +745,12 @@ main (int argc, char **argv)
      early as possible.  (unexw32.c calls this function as well, but
      the additional call here is harmless.) */
   cache_system_info ();
      early as possible.  (unexw32.c calls this function as well, but
      the additional call here is harmless.) */
   cache_system_info ();
+#ifdef WINDOWSNT
+  /* On Windows 9X, we have to load UNICOWS.DLL as early as possible,
+     to have non-stub implementations of APIs we need to convert file
+     names between UTF-8 and the system's ANSI codepage.  */
+  maybe_load_unicows_dll ();
+#endif
 #endif
 
 #ifdef RUN_TIME_REMAP
 #endif
 
 #ifdef RUN_TIME_REMAP
@@ -764,6 +766,10 @@ main (int argc, char **argv)
 
   atexit (close_output_streams);
 
 
   atexit (close_output_streams);
 
+  /* Override Guile's libgc configuration. */
+  xputenv ("GC_ALL_INTERIOR_POINTERS=1");
+  scm_init_guile ();
+
   sort_args (argc, argv);
   argc = 0;
   while (argv[argc]) argc++;
   sort_args (argc, argv);
   argc = 0;
   while (argv[argc]) argc++;
@@ -888,9 +894,6 @@ main (int argc, char **argv)
     }
 #endif /* HAVE_SETRLIMIT and RLIMIT_STACK */
 
     }
 #endif /* HAVE_SETRLIMIT and RLIMIT_STACK */
 
-  /* Record (approximately) where the stack begins.  */
-  stack_bottom = &stack_bottom_variable;
-
   clearerr (stdin);
 
 #ifndef SYSTEM_MALLOC
   clearerr (stdin);
 
 #ifndef SYSTEM_MALLOC
@@ -994,11 +997,14 @@ main (int argc, char **argv)
     {
       int i;
       printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]);
     {
       int i;
       printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]);
-      for (i = 0; i < sizeof usage_message / sizeof *usage_message; i++)
+      for (i = 0; i < ARRAYELTS (usage_message); i++)
        fputs (usage_message[i], stdout);
       exit (0);
     }
 
        fputs (usage_message[i], stdout);
       exit (0);
     }
 
+  /* Make sure IS_DAEMON starts up as false.  */
+  daemon_pipe[1] = 0;
+
   if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
       || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args))
     {
   if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
       || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args))
     {
@@ -1153,6 +1159,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
   if (!initialized)
     {
       init_alloc_once ();
   if (!initialized)
     {
       init_alloc_once ();
+      init_fns_once ();
       init_obarray ();
       init_eval_once ();
       init_charset_once ();
       init_obarray ();
       init_eval_once ();
       init_charset_once ();
@@ -1221,7 +1228,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
 #ifdef HAVE_NS
   ns_pool = ns_alloc_autorelease_pool ();
 #ifdef NS_IMPL_GNUSTEP
 #ifdef HAVE_NS
   ns_pool = ns_alloc_autorelease_pool ();
 #ifdef NS_IMPL_GNUSTEP
-  /* GNUStep stupidly resets our locale settings after we made them.  */
+  /* GNUstep stupidly resets our locale settings after we made them.  */
   fixup_locale ();
 #endif
 
   fixup_locale ();
 #endif
 
@@ -1359,7 +1366,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
   xputenv ("LANG=C");
 #endif
 
   xputenv ("LANG=C");
 #endif
 
-  init_buffer ();      /* Init default directory of main buffer.  */
+  /* Init buffer storage and default directory of main buffer.  */
+  init_buffer (initialized);
 
   init_callproc_1 ();  /* Must precede init_cmdargs and init_sys_modes.  */
 
 
   init_callproc_1 ();  /* Must precede init_cmdargs and init_sys_modes.  */
 
@@ -1769,8 +1777,8 @@ sort_args (int argc, char **argv)
      0 for an option that takes no arguments,
      1 for an option that takes one argument, etc.
      -1 for an ordinary non-option argument.  */
      0 for an option that takes no arguments,
      1 for an option that takes one argument, etc.
      -1 for an ordinary non-option argument.  */
-  int *options = xnmalloc (argc, sizeof *options);
-  int *priority = xnmalloc (argc, sizeof *priority);
+  int *options = xnmalloc_atomic (argc, sizeof *options);
+  int *priority = xnmalloc_atomic (argc, sizeof *priority);
   int to = 1;
   int incoming_used = 1;
   int from;
   int to = 1;
   int incoming_used = 1;
   int from;
@@ -1800,7 +1808,7 @@ sort_args (int argc, char **argv)
            }
 
          /* Look for a match with a known old-fashioned option.  */
            }
 
          /* Look for a match with a known old-fashioned option.  */
-         for (i = 0; i < sizeof (standard_args) / sizeof (standard_args[0]); i++)
+         for (i = 0; i < ARRAYELTS (standard_args); i++)
            if (!strcmp (argv[from], standard_args[i].name))
              {
                options[from] = standard_args[i].nargs;
            if (!strcmp (argv[from], standard_args[i].name))
              {
                options[from] = standard_args[i].nargs;
@@ -1822,8 +1830,7 @@ sort_args (int argc, char **argv)
 
              match = -1;
 
 
              match = -1;
 
-             for (i = 0;
-                  i < sizeof (standard_args) / sizeof (standard_args[0]); i++)
+             for (i = 0; i < ARRAYELTS (standard_args); i++)
                if (standard_args[i].longname
                    && !strncmp (argv[from], standard_args[i].longname,
                                 thislen))
                if (standard_args[i].longname
                    && !strncmp (argv[from], standard_args[i].longname,
                                 thislen))
@@ -2016,9 +2023,7 @@ shut_down_emacs (int sig, Lisp_Object stuff)
   kill_buffer_processes (Qnil);
   Fdo_auto_save (Qt, Qnil);
 
   kill_buffer_processes (Qnil);
   Fdo_auto_save (Qt, Qnil);
 
-#ifdef CLASH_DETECTION
   unlock_all_files ();
   unlock_all_files ();
-#endif
 
   /* There is a tendency for a SIGIO signal to arrive within exit,
      and cause a SIGHUP because the input descriptor is already closed.  */
 
   /* There is a tendency for a SIGIO signal to arrive within exit,
      and cause a SIGHUP because the input descriptor is already closed.  */
@@ -2066,13 +2071,16 @@ You must run Emacs in batch mode in order to dump it.  */)
 {
   Lisp_Object tem;
   Lisp_Object symbol;
 {
   Lisp_Object tem;
   Lisp_Object symbol;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
 
   check_pure_size ();
 
   if (! noninteractive)
     error ("Dumping Emacs works only in batch mode");
 
 
   check_pure_size ();
 
   if (! noninteractive)
     error ("Dumping Emacs works only in batch mode");
 
+  if (!might_dump)
+    error ("Emacs can be dumped only once");
+
 #ifdef GNU_LINUX
 
   /* Warn if the gap between BSS end and heap start is larger than this.  */
 #ifdef GNU_LINUX
 
   /* Warn if the gap between BSS end and heap start is larger than this.  */
@@ -2138,13 +2146,8 @@ You must run Emacs in batch mode in order to dump it.  */)
   malloc_state_ptr = malloc_get_state ();
 #endif
 
   malloc_state_ptr = malloc_get_state ();
 #endif
 
-#ifdef USE_MMAP_FOR_BUFFERS
-  mmap_set_vars (0);
-#endif
   unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0);
   unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0);
-#ifdef USE_MMAP_FOR_BUFFERS
-  mmap_set_vars (1);
-#endif
+
 #ifdef DOUG_LEA_MALLOC
   free (malloc_state_ptr);
 #endif
 #ifdef DOUG_LEA_MALLOC
   free (malloc_state_ptr);
 #endif
@@ -2158,7 +2161,8 @@ You must run Emacs in batch mode in order to dump it.  */)
 
   Vpurify_flag = tem;
 
 
   Vpurify_flag = tem;
 
-  return unbind_to (count, Qnil);
+  dynwind_end ();
+  return Qnil;
 }
 
 #endif /* not CANNOT_DUMP */
 }
 
 #endif /* not CANNOT_DUMP */
@@ -2398,22 +2402,13 @@ from the parent process and its tty file descriptors.  */)
 void
 syms_of_emacs (void)
 {
 void
 syms_of_emacs (void)
 {
+#include "emacs.x"
+
   DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist");
   DEFSYM (Qrisky_local_variable, "risky-local-variable");
   DEFSYM (Qkill_emacs, "kill-emacs");
   DEFSYM (Qkill_emacs_hook, "kill-emacs-hook");
 
   DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist");
   DEFSYM (Qrisky_local_variable, "risky-local-variable");
   DEFSYM (Qkill_emacs, "kill-emacs");
   DEFSYM (Qkill_emacs_hook, "kill-emacs-hook");
 
-#ifndef CANNOT_DUMP
-  defsubr (&Sdump_emacs);
-#endif
-
-  defsubr (&Skill_emacs);
-
-  defsubr (&Sinvocation_name);
-  defsubr (&Sinvocation_directory);
-  defsubr (&Sdaemonp);
-  defsubr (&Sdaemon_initialized);
-
   DEFVAR_LISP ("command-line-args", Vcommand_line_args,
               doc: /* Args passed by shell to Emacs, as a list of strings.
 Many arguments are deleted from the list as they are processed.  */);
   DEFVAR_LISP ("command-line-args", Vcommand_line_args,
               doc: /* Args passed by shell to Emacs, as a list of strings.
 Many arguments are deleted from the list as they are processed.  */);
@@ -2443,6 +2438,12 @@ Emacs is running.  */);
               doc: /* String containing the configuration options Emacs was built with.  */);
   Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS);
 
               doc: /* String containing the configuration options Emacs was built with.  */);
   Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS);
 
+  DEFVAR_LISP ("system-configuration-features", Vsystem_configuration_features,
+              doc: /* String listing some of the main features this Emacs was compiled with.
+An element of the form \"FOO\" generally means that HAVE_FOO was
+defined during the build.  */);
+  Vsystem_configuration_features = build_string (EMACS_CONFIG_FEATURES);
+
   DEFVAR_BOOL ("noninteractive", noninteractive1,
               doc: /* Non-nil means Emacs is running without interactive terminal.  */);
 
   DEFVAR_BOOL ("noninteractive", noninteractive1,
               doc: /* Non-nil means Emacs is running without interactive terminal.  */);
 
@@ -2520,6 +2521,10 @@ This is nil during initialization.  */);
               doc: /* Version numbers of this version of Emacs.  */);
   Vemacs_version = build_string (emacs_version);
 
               doc: /* Version numbers of this version of Emacs.  */);
   Vemacs_version = build_string (emacs_version);
 
+  DEFVAR_LISP ("report-emacs-bug-address", Vreport_emacs_bug_address,
+              doc: /* Address of mailing list for GNU Emacs bugs.  */);
+  Vreport_emacs_bug_address = build_string (emacs_bugreport);
+
   DEFVAR_LISP ("dynamic-library-alist", Vdynamic_library_alist,
     doc: /* Alist of dynamic libraries vs external files implementing them.
 Each element is a list (LIBRARY FILE...), where the car is a symbol
   DEFVAR_LISP ("dynamic-library-alist", Vdynamic_library_alist,
     doc: /* Alist of dynamic libraries vs external files implementing them.
 Each element is a list (LIBRARY FILE...), where the car is a symbol
@@ -2542,7 +2547,4 @@ libraries; only those already known by Emacs will be loaded.  */);
   Vlibrary_cache = Qnil;
   staticpro (&Vlibrary_cache);
 #endif
   Vlibrary_cache = Qnil;
   staticpro (&Vlibrary_cache);
 #endif
-
-  /* Make sure IS_DAEMON starts up as false.  */
-  daemon_pipe[1] = 0;
 }
 }