]> code.delx.au - gnu-emacs/blobdiff - src/emacs.c
(Fset_char_table_parent): Fix previous change.
[gnu-emacs] / src / emacs.c
index d0bcd1c540aea0b09b9a51d442ca1d35de89325f..4f0d70cbbe1c8e806f9fb15ffa1bd51bff7cf675 100644 (file)
@@ -1,5 +1,5 @@
 /* Fully extensible Emacs, running on Unix, intended for GNU.
-   Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -35,12 +35,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/ioctl.h>
 #endif
 
-#ifdef APOLLO
-#ifndef APOLLO_SR10
-#include <default_acl.h>
-#endif
-#endif
-
 #include "lisp.h"
 #include "commands.h"
 #include "intervals.h"
@@ -84,7 +78,11 @@ Lisp_Object Vsystem_type;
 
 /* Variable whose value is string giving configuration built for.  */
 Lisp_Object Vsystem_configuration;
-  
+
+/* Variable whose value is string giving configuration options,
+   for use when reporting bugs.  */
+Lisp_Object Vsystem_configuration_options;
+
 /* If non-zero, emacs should not attempt to use an window-specific code,
    but instead should use the virtual terminal under which it was started */
 int inhibit_window_system;
@@ -94,7 +92,11 @@ int inhibit_window_system;
    priority; Those functions have their own extern declaration.  */
 int emacs_priority;
 
-#ifdef BSD
+/* If non-zero a filter or a sentinel is running.  Tested to save the match
+   data on the first attempt to change it inside asynchronous code. */
+int running_asynch_code;
+
+#ifdef BSD_PGRPS
 /* See sysdep.c.  */
 extern int inherited_pgroup;
 #endif
@@ -108,9 +110,11 @@ int display_arg;
    Tells GC how to save a copy of the stack.  */
 char *stack_bottom;
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 extern Lisp_Object Vwindow_system;
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
+
+extern Lisp_Object Vauto_save_list_file_name;
 
 #ifdef USG_SHARED_LIBRARIES
 /* If nonzero, this is the place to put the end of the writable segment
@@ -128,6 +132,12 @@ int noninteractive;
    but nothing terrible happens if user sets this one.  */
 
 int noninteractive1;
+
+/* Save argv and argc.  */
+char **initial_argv;
+int initial_argc;
+
+static void sort_args ();
 \f
 /* Signal code for the fatal signal that was received */
 int fatal_error_code;
@@ -175,6 +185,9 @@ memory_warning_signal (sig)
   signal (sig, memory_warning_signal);
 
   malloc_warning ("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
 \f
@@ -189,6 +202,9 @@ init_cmdargs (argc, argv, skip_args)
   register int i;
   Lisp_Object name, dir;
 
+  initial_argv = argv;
+  initial_argc = argc;
+
   Vinvocation_name = Ffile_name_nondirectory (build_string (argv[0]));
   Vinvocation_directory = Ffile_name_directory (build_string (argv[0]));
   /* If we got no directory in argv[0], search PATH to find where
@@ -202,6 +218,11 @@ init_cmdargs (argc, argv, skip_args)
        Vinvocation_directory = Ffile_name_directory (found);
     }
 
+  if (!NILP (Vinvocation_directory)
+      && NILP (Ffile_name_absolute_p (Vinvocation_directory)))
+    /* Emacs was started with relative path, like ./emacs  */
+    Vinvocation_directory = Fexpand_file_name (Vinvocation_directory, Qnil);
+
   Vinstallation_directory = Qnil;
 
   if (!NILP (Vinvocation_directory))
@@ -210,57 +231,39 @@ init_cmdargs (argc, argv, skip_args)
       name = Fexpand_file_name (Vinvocation_name, dir);
       while (1)
        {
-         Lisp_Object tem, lisp_exists, lib_src_exists;
+         Lisp_Object tem, lib_src_exists;
          Lisp_Object etc_exists, info_exists;
 
-         /* See if dir contains subdirs for use by Emacs.  */
-         tem = Fexpand_file_name (build_string ("lisp"), dir);
-         lisp_exists = Ffile_exists_p (tem);
-         if (!NILP (lisp_exists))
+         /* See if dir contains subdirs for use by Emacs.
+            Check for the ones that would exist in a build directory,
+            not including lisp and info.  */
+         tem = Fexpand_file_name (build_string ("lib-src"), dir);
+         lib_src_exists = Ffile_exists_p (tem);
+         if (!NILP (lib_src_exists))
            {
-             tem = Fexpand_file_name (build_string ("lib-src"), dir);
-             lib_src_exists = Ffile_exists_p (tem);
-             if (!NILP (lib_src_exists))
+             tem = Fexpand_file_name (build_string ("etc"), dir);
+             etc_exists = Ffile_exists_p (tem);
+             if (!NILP (etc_exists))
                {
-                 tem = Fexpand_file_name (build_string ("etc"), dir);
-                 etc_exists = Ffile_exists_p (tem);
-                 if (!NILP (etc_exists))
-                   {
-                     tem = Fexpand_file_name (build_string ("info"), dir);
-                     info_exists = Ffile_exists_p (tem);
-                     if (!NILP (info_exists))
-                       {
-                         Vinstallation_directory
-                           = Ffile_name_as_directory (dir);
-                         break;
-                       }
-                   }
+                 Vinstallation_directory
+                   = Ffile_name_as_directory (dir);
+                 break;
                }
            }
 
          /* See if dir's parent contains those subdirs.  */
-         tem = Fexpand_file_name (build_string ("../lisp"), dir);
-         lisp_exists = Ffile_exists_p (tem);
-         if (!NILP (lisp_exists))
+         tem = Fexpand_file_name (build_string ("../lib-src"), dir);
+         lib_src_exists = Ffile_exists_p (tem);
+         if (!NILP (lib_src_exists))
            {
-             tem = Fexpand_file_name (build_string ("../lib-src"), dir);
-             lib_src_exists = Ffile_exists_p (tem);
-             if (!NILP (lib_src_exists))
+             tem = Fexpand_file_name (build_string ("../etc"), dir);
+             etc_exists = Ffile_exists_p (tem);
+             if (!NILP (etc_exists))
                {
-                 tem = Fexpand_file_name (build_string ("../etc"), dir);
-                 etc_exists = Ffile_exists_p (tem);
-                 if (!NILP (etc_exists))
-                   {
-                     tem = Fexpand_file_name (build_string ("../info"), dir);
-                     info_exists = Ffile_exists_p (tem);
-                     if (!NILP (info_exists))
-                       {
-                         tem = Fexpand_file_name (build_string (".."), dir);
-                         Vinstallation_directory
-                           = Ffile_name_as_directory (tem);
-                         break;
-                       }
-                   }
+                 tem = Fexpand_file_name (build_string (".."), dir);
+                 Vinstallation_directory
+                   = Ffile_name_as_directory (tem);
+                 break;
                }
            }
 
@@ -269,7 +272,7 @@ init_cmdargs (argc, argv, skip_args)
          tem = Ffile_symlink_p (name);
          if (!NILP (tem))
            {
-             name = tem;
+             name = Fexpand_file_name (tem, dir);
              dir = Ffile_name_directory (name);
            }
          else
@@ -306,9 +309,9 @@ DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
 \f
 #ifdef VMS
 #ifdef LINK_CRTL_SHARE
-#ifdef SHAREABLE_LIB_BUG
+#ifdef SHARABLE_LIB_BUG
 extern noshare char **environ;
-#endif /* SHAREABLE_LIB_BUG */
+#endif /* SHARABLE_LIB_BUG */
 #endif /* LINK_CRTL_SHARE */
 #endif /* VMS */
 
@@ -336,6 +339,75 @@ __main ()
 #endif /* __GNUC__ */
 #endif /* ORDINARY_LINK */
 
+/* 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
+   (the argument is supposed to have a value) store in *VALPTR either
+   the next argument or the portion of this one after the equal sign.
+   ARGV is read starting at position *SKIPPTR; this index is advanced
+   by the number of arguments used.
+
+   Too bad we can't just use getopt for all of this, but we don't have
+   enough information to do it right.  */
+
+static int
+argmatch (argv, argc, sstr, lstr, minlen, valptr, skipptr)
+     char **argv;
+     int argc;
+     char *sstr;
+     char *lstr;
+     int minlen;
+     char **valptr;
+     int *skipptr;
+{
+  char *p;
+  int arglen;
+  char *arg;
+
+  /* Don't access argv[argc]; give up in advance.  */
+  if (argc <= *skipptr + 1)
+    return 0;
+
+  arg = argv[*skipptr+1];
+  if (arg == NULL)
+    return 0;
+  if (strcmp (arg, sstr) == 0)
+    {
+      if (valptr != NULL)
+       {
+         *valptr = argv[*skipptr+2];
+         *skipptr += 2;
+       }
+      else
+       *skipptr += 1;
+      return 1;
+    }
+  arglen = (valptr != NULL && (p = index (arg, '=')) != NULL
+           ? p - arg : strlen (arg));
+  if (lstr == 0 || arglen < minlen || strncmp (arg, lstr, arglen) != 0)
+    return 0;
+  else if (valptr == NULL)
+    {
+      *skipptr += 1;
+      return 1;
+    }
+  else if (p != NULL)
+    {
+      *valptr = p+1;
+      *skipptr += 1;
+      return 1;
+    }
+  else if (argv[*skipptr+2] != NULL)
+    {
+      *valptr = argv[*skipptr+2];
+      *skipptr += 2;
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
 /* ARGSUSED */
 main (argc, argv, envp)
      int argc;
@@ -347,9 +419,31 @@ main (argc, argv, envp)
   extern int errno;
   extern sys_nerr;
 
+#ifdef LINUX_SBRK_BUG
+  __sbrk (1);
+#endif
+
+  sort_args (argc, argv);
+
+  if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args))
+    {
+      Lisp_Object tem;
+      tem = Fsymbol_value (intern ("emacs-version"));
+      if (!STRINGP (tem))
+       {
+         fprintf (stderr, "Invalid value of `emacs-version'\n");
+         exit (1);
+       }
+      else
+       {
+         printf ("%s\n", XSTRING (tem)->data);
+         exit (0);
+       }
+    }
+
 /* Map in shared memory, if we are using that.  */
 #ifdef HAVE_SHM
-  if (argc > 1 && !strcmp (argv[1], "-nl"))
+  if (argmatch (argv, argc, "-nl", "--no-shared-memory", 6, NULL, &skip_args))
     {
       map_in_data (0);
       /* The shared memory was just restored, which clobbered this.  */
@@ -364,38 +458,25 @@ main (argc, argv, envp)
 #endif
 
 #ifdef NeXT
-  extern int malloc_cookie;
-
-  /* This helps out unexnext.c.  */
-  if (initialized)
-    if (malloc_jumpstart (malloc_cookie) != 0)
-      printf ("malloc jumpstart failed!\n");
-#endif /* NeXT */
-
-#ifdef HAVE_X_WINDOWS
-  /* Stupid kludge to catch command-line display spec.  We can't
-     handle this argument entirely in window system dependent code
-     because we don't even know which window system dependent code
-     to run until we've recognized this argument.  */
   {
-    int i;
-
-    for (i = 1; (i < argc && ! display_arg); i++)
-      if (!strcmp (argv[i], "-d") || !strcmp (argv[i], "-display"))
-       display_arg = 1;
+    extern int malloc_cookie;
+    /* This helps out unexnext.c.  */
+    if (initialized)
+      if (malloc_jumpstart (malloc_cookie) != 0)
+       printf ("malloc jumpstart failed!\n");
   }
-#endif
+#endif /* NeXT */
 
 #ifdef VMS
   /* If -map specified, map the data file in */
-  if (argc > 2 && ! strcmp (argv[1], "-map"))
-    {
-      skip_args = 2;
-      mapin_data (argv[2]);
-    }
+  {
+    char *file;
+    if (argmatch (argv, argc, "-map", "--map-data", 3, &mapin_file, &skip_args))
+      mapin_data (file);
+  }
 
 #ifdef LINK_CRTL_SHARE
-#ifdef SHAREABLE_LIB_BUG
+#ifdef SHARABLE_LIB_BUG
   /* Bletcherous shared libraries! */
   if (!stdin)
     stdin = fdopen (0, "r");
@@ -405,7 +486,7 @@ main (argc, argv, envp)
     stderr = fdopen (2, "w");
   if (!environ)
     environ = envp;
-#endif /* SHAREABLE_LIB_BUG */
+#endif /* SHARABLE_LIB_BUG */
 #endif /* LINK_CRTL_SHARE */
 #endif /* VMS */
 
@@ -419,33 +500,11 @@ main (argc, argv, envp)
 
 #ifdef USG_SHARED_LIBRARIES
   if (bss_end)
-    brk (bss_end);
+    brk ((void *)bss_end);
 #endif
 
   clearerr (stdin);
 
-#ifdef BSD_PGRPS
-  if (initialized)
-    {
-      inherited_pgroup = EMACS_GETPGRP (0);
-      setpgrp (0, getpid ());
-    }
-#else
-#if defined (USG5) && defined (INTERRUPT_INPUT)
-  setpgrp ();
-#endif
-#endif
-
-
-#ifdef APOLLO
-#ifndef APOLLO_SR10
-  /* If USE_DOMAIN_ACLS environment variable exists,
-     use ACLs rather than UNIX modes. */
-  if (egetenv ("USE_DOMAIN_ACLS"))
-    default_acl (USE_DEFACL);
-#endif
-#endif /* APOLLO */
-
 #ifndef SYSTEM_MALLOC
   if (! initialized)
     {
@@ -467,53 +526,120 @@ main (argc, argv, envp)
   (stderr)->_flag &= ~_IOTEXT;
 #endif /* MSDOS */
 
-#ifdef PRIO_PROCESS
+#ifdef SET_EMACS_PRIORITY
   if (emacs_priority)
     nice (emacs_priority);
   setuid (getuid ());
-#endif /* PRIO_PROCESS */
+#endif /* SET_EMACS_PRIORITY */
+
+#ifdef EXTRA_INITIALIZE
+  EXTRA_INITIALIZE;
+#endif
 
   inhibit_window_system = 0;
 
   /* Handle the -t switch, which specifies filename to use as terminal */
-  if (skip_args + 2 < argc && !strcmp (argv[skip_args + 1], "-t"))
-    {
-      int result;
-      skip_args += 2;
-      close (0);
-      close (1);
-      result = open (argv[skip_args], O_RDWR, 2 );
-      if (result < 0)
-       {
-         char *errstring = strerror (errno);
-         fprintf (stderr, "emacs: %s: %s\n", argv[skip_args], errstring);
-         exit (1);
-       }
-      dup (0);
-      if (! isatty (0))
-       {
-         fprintf (stderr, "emacs: %s: not a tty\n", argv[skip_args]);
-         exit (1);
-       }
-      fprintf (stderr, "Using %s\n", argv[skip_args]);
-#ifdef HAVE_X_WINDOWS
-      inhibit_window_system = 1;       /* -t => -nw */
+  {
+    char *term;
+    if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args))
+      {
+       int result;
+       close (0);
+       close (1);
+       result = open (term, O_RDWR, 2 );
+       if (result < 0)
+         {
+           char *errstring = strerror (errno);
+           fprintf (stderr, "emacs: %s: %s\n", term, errstring);
+           exit (1);
+         }
+       dup (0);
+       if (! isatty (0))
+         {
+           fprintf (stderr, "emacs: %s: not a tty\n", term);
+           exit (1);
+         }
+       fprintf (stderr, "Using %s\n", term);
+#ifdef HAVE_WINDOW_SYSTEM
+       inhibit_window_system = 1; /* -t => -nw */
 #endif
-    }
+      }
+  }
+  if (argmatch (argv, argc, "-nw", "--no-windows", 6, NULL, &skip_args))
+    inhibit_window_system = 1;
 
-  if (skip_args + 1 < argc
-      && (!strcmp (argv[skip_args + 1], "-nw")))
+  /* Handle the -batch switch, which means don't do interactive display.  */
+  noninteractive = 0;
+  if (argmatch (argv, argc, "-batch", "--batch", 5, NULL, &skip_args))
+    noninteractive = 1;
+
+  /* Handle the --help option, which gives a usage message..  */
+  if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args))
     {
-      skip_args += 1;
-      inhibit_window_system = 1;
+      printf ("\
+Usage: %s [-t term] [--terminal term]  [-nw] [--no-windows]  [--batch]\n\
+      [-q] [--no-init-file]  [-u user] [--user user]  [--debug-init]\n\
+      [--version] [--no-site-file]\n\
+      [-f func] [--funcall func]  [-l file] [--load file]  [--insert file]\n\
+      [+linenum] file-to-visit  [--kill]\n", argv[0]);
+      exit (0);
     }
 
-/* Handle the -batch switch, which means don't do interactive display.  */
-  noninteractive = 0;
-  if (skip_args + 1 < argc && !strcmp (argv[skip_args + 1], "-batch"))
+#ifdef HAVE_X_WINDOWS
+  /* Stupid kludge to catch command-line display spec.  We can't
+     handle this argument entirely in window system dependent code
+     because we don't even know which window system dependent code
+     to run until we've recognized this argument.  */
+  {
+    char *displayname;
+    int i;
+    int count_before = skip_args;
+
+    if (argmatch (argv, argc, "-d", "--display", 3, &displayname, &skip_args))
+      display_arg = 1;
+    else if (argmatch (argv, argc, "-display", 0, 3, &displayname, &skip_args))
+      display_arg = 1;
+
+    /* If we have the form --display=NAME,
+       convert it into  -d name.
+       This requires inserting a new element into argv.  */
+    if (displayname != 0 && skip_args - count_before == 1)
+      {
+       char **new = (char **) xmalloc (sizeof (char *) * (argc + 2));
+       int j;
+
+       for (j = 0; j < count_before + 1; j++)
+         new[j] = argv[j];
+       new[count_before + 1] = "-d";
+       new[count_before + 2] = displayname;
+       for (j = count_before + 2; j <argc; j++)
+         new[j + 1] = argv[j];
+       argv = new;
+       argc++;
+      }
+    /* Change --display to -d, when its arg is separate.  */
+    else if (displayname != 0 && skip_args > count_before
+            && argv[count_before + 1][1] == '-')
+      argv[count_before + 1] = "-d";
+
+    /* Don't actually discard this arg.  */
+    skip_args = count_before;
+  }
+#endif
+
+  if (! noninteractive)
     {
-      skip_args += 1;
-      noninteractive = 1;
+#ifdef BSD_PGRPS
+      if (initialized)
+       {
+         inherited_pgroup = EMACS_GETPGRP (0);
+         setpgrp (0, getpid ());
+       }
+#else
+#if defined (USG5) && defined (INTERRUPT_INPUT)
+      setpgrp ();
+#endif
+#endif
     }
 
 #ifdef POSIX_SIGNALS
@@ -535,6 +661,27 @@ main (argc, argv, envp)
       signal (SIGQUIT, fatal_error_signal);
       signal (SIGILL, fatal_error_signal);
       signal (SIGTRAP, fatal_error_signal);
+#ifdef SIGABRT
+      signal (SIGABRT, fatal_error_signal);
+#endif
+#ifdef SIGHWE
+      signal (SIGHWE, fatal_error_signal);
+#endif
+#ifdef SIGPRE
+      signal (SIGPRE, fatal_error_signal);
+#endif
+#ifdef SIGORE
+      signal (SIGORE, fatal_error_signal);
+#endif
+#ifdef SIGUME
+      signal (SIGUME, fatal_error_signal);
+#endif
+#ifdef SIGDLK
+      signal (SIGDLK, fatal_error_signal);
+#endif
+#ifdef SIGCPULIM
+      signal (SIGCPULIM, fatal_error_signal);
+#endif
 #ifdef SIGIOT
       /* This is missing on some systems - OS/2, for example.  */
       signal (SIGIOT, fatal_error_signal);
@@ -597,12 +744,19 @@ main (argc, argv, envp)
   init_alloc ();
   init_eval ();
   init_data ();
+  running_asynch_code = 0;
 
 #ifdef MSDOS
   /* Call early 'cause init_environment needs it.  */
   init_dosfns ();
   /* Set defaults for several environment variables.  */
   if (initialized) init_environment (argc, argv, skip_args);
+  else init_gettimeofday ();
+#endif
+
+#ifdef WINDOWSNT
+  /* Initialize environment from registry settings.  */
+  init_environment ();
 #endif
 
   /* egetenv is a pretty low-level facility, which may get called in
@@ -711,11 +865,24 @@ main (argc, argv, envp)
 #ifdef HAVE_X11
       syms_of_xselect ();
 #endif
-#ifdef HAVE_X_MENU
-      syms_of_xmenu ();
-#endif /* HAVE_X_MENU */
 #endif /* HAVE_X_WINDOWS */
 
+#if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
+      syms_of_xfaces ();
+#endif
+
+#ifdef HAVE_MENUS
+      syms_of_xmenu ();
+#endif /* HAVE_MENUS */
+
+#ifdef HAVE_NTGUI
+      syms_of_win32term ();
+      syms_of_win32fns ();
+      syms_of_win32faces ();
+      syms_of_win32select ();
+      syms_of_win32menu ();
+#endif /* HAVE_NTGUI */
+
 #ifdef SYMS_SYSTEM
       SYMS_SYSTEM;
 #endif
@@ -737,34 +904,234 @@ main (argc, argv, envp)
 
   if (!initialized)
     {
+      char *file;
       /* Handle -l loadup-and-dump, args passed by Makefile. */
-      if (argc > 2 + skip_args && !strcmp (argv[1 + skip_args], "-l"))
+      if (argmatch (argv, argc, "-l", "--load", 3, &file, &skip_args))
        Vtop_level = Fcons (intern ("load"),
-                           Fcons (build_string (argv[2 + skip_args]), Qnil));
+                           Fcons (build_string (file), Qnil));
 #ifdef CANNOT_DUMP
       /* Unless next switch is -nl, load "loadup.el" first thing.  */
-      if (!(argc > 1 + skip_args && !strcmp (argv[1 + skip_args], "-nl")))
+      if (!argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args))
        Vtop_level = Fcons (intern ("load"),
                            Fcons (build_string ("loadup.el"), Qnil));
 #endif /* CANNOT_DUMP */
     }
 
+  if (initialized)
+    {
+      /* Erase any pre-dump messages in the message log, to avoid confusion */
+      Lisp_Object old_log_max;
+      old_log_max = Vmessage_log_max;
+      XSETFASTINT (Vmessage_log_max, 0);
+      message_dolog ("", 0, 1);
+      Vmessage_log_max = old_log_max;
+    }
+
   initialized = 1;
 
-#if defined (sun) || defined (LOCALTIME_CACHE)
-  /* sun's localtime has a bug.  it caches the value of the time
+#ifdef LOCALTIME_CACHE
+  /* Some versions of localtime have a bug.  They cache the value of the time
      zone rather than looking it up every time.  Since localtime() is
      called to bolt the undumping time into the undumped emacs, this
      results in localtime ignoring the TZ environment variable.
      This flushes the new TZ value into localtime. */
   tzset ();
-#endif /* defined (sun) || defined (LOCALTIME_CACHE) */
+#endif /* defined (LOCALTIME_CACHE) */
 
   /* Enter editor command loop.  This never returns.  */
   Frecursive_edit ();
   /* NOTREACHED */
 }
 \f
+/* Sort the args so we can find the most important ones
+   at the beginning of argv.  */
+
+/* First, here's a table of all the standard options.  */
+
+struct standard_args
+{
+  char *name;
+  char *longname;
+  int priority;
+  int nargs;
+};
+
+struct standard_args standard_args[] =
+{
+  { "-version", "--version", 110, 0 },
+  { "-help", "--help", 110, 0 },
+  { "-nl", "--no-shared-memory", 100, 0 },
+#ifdef VMS
+  { "-map", "--map-data", 100, 0 },
+#endif
+  { "-t", "--terminal", 90, 1 },
+  { "-d", "--display", 80, 1 },
+  { "-display", 0, 80, 1 },
+  { "-nw", "--no-windows", 70, 0 },
+  { "-batch", "--batch", 60, 0 },
+  { "-q", "--no-init-file", 50, 0 },
+  { "-no-init-file", 0, 50, 0 },
+  { "-no-site-file", "--no-site-file", 40, 0 },
+  { "-u", "--user", 30, 1 },
+  { "-user", 0, 30, 1 },
+  { "-debug-init", "--debug-init", 20, 0 },
+  { "-i", "--icon-type", 15, 0 },
+  { "-itype", 0, 15, 0 },
+  { "-iconic", "--iconic", 15, 0 },
+  { "-bg", "--background-color", 10, 1 },
+  { "-background", 0, 10, 1 },
+  { "-fg", "--foreground-color", 10, 1 },
+  { "-foreground", 0, 10, 1 },
+  { "-bd", "--border-color", 10, 1 },
+  { "-bw", "--border-width", 10, 1 },
+  { "-ib", "--internal-border", 10, 1 },
+  { "-ms", "--mouse-color", 10, 1 },
+  { "-cr", "--cursor-color", 10, 1 },
+  { "-fn", "--font", 10, 1 },
+  { "-font", 0, 10, 1 },
+  { "-g", "--geometry", 10, 1 },
+  { "-geometry", 0, 10, 1 },
+  { "-T", "--title", 10, 1 },
+  { "-name", "--name", 10, 1 },
+  { "-xrm", "--xrm", 10, 1 },
+  { "-r", "--reverse-video", 5, 0 },
+  { "-rv", 0, 5, 0 },
+  { "-reverse", 0, 5, 0 },
+  { "-vb", "--vertical-scroll-bars", 5, 0 },
+  /* These have the same priority as ordinary file name args,
+     so they are not reordered with respect to those.  */
+  { "-L", "--directory", 0, 1 },
+  { "-directory", 0, 0, 1 },
+  { "-l", "--load", 0, 1 },
+  { "-load", 0, 0, 1 },
+  { "-f", "--funcall", 0, 1 },
+  { "-funcall", 0, 0, 1 },
+  { "-eval", "--eval", 0, 1 },
+  { "-insert", "--insert", 0, 1 },
+  /* This should be processed after ordinary file name args and the like.  */
+  { "-kill", "--kill", -10, 0 },
+};
+
+/* Reorder the elements of ARGV (assumed to have ARGC elements)
+   so that the highest priority ones come first.
+   Do not change the order of elements of equal priority.
+   If an option takes an argument, keep it and its argument together.  */
+
+static void
+sort_args (argc, argv)
+     int argc;
+     char **argv;
+{
+  char **new = (char **) xmalloc (sizeof (char *) * argc);
+  /* For each element of argv,
+     the corresponding element of options is:
+     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 = (int *) xmalloc (sizeof (int) * argc);
+  int *priority = (int *) xmalloc (sizeof (int) * argc);
+  int to = 1;
+  int from;
+  int i;
+
+  /* Categorize all the options,
+     and figure out which argv elts are option arguments.  */
+  for (from = 1; from < argc; from++)
+    {
+      options[from] = -1;
+      priority[from] = 0;
+      if (argv[from][0] == '-')
+       {
+         int match, thislen;
+         char *equals;
+
+         /* Look for a match with a known old-fashioned option.  */
+         for (i = 0; i < sizeof (standard_args) / sizeof (standard_args[0]); i++)
+           if (!strcmp (argv[from], standard_args[i].name))
+             {
+               options[from] = standard_args[i].nargs;
+               priority[from] = standard_args[i].priority;
+               from += standard_args[i].nargs;
+               goto done;
+             }
+
+         /* Look for a match with a known long option.
+            MATCH is -1 if no match so far, -2 if two or more matches so far,
+            >= 0 (the table index of the match) if just one match so far.  */
+         if (argv[from][1] == '-')
+           {
+             match = -1;
+             thislen = strlen (argv[from]);
+             equals = index (argv[from], '=');
+             if (equals != 0)
+               thislen = equals - argv[from];
+
+             for (i = 0;
+                  i < sizeof (standard_args) / sizeof (standard_args[0]); i++)
+               if (standard_args[i].longname
+                   && !strncmp (argv[from], standard_args[i].longname,
+                                thislen))
+                 {
+                   if (match == -1)
+                     match = i;
+                   else
+                     match = -2;
+                 }
+
+             /* If we found exactly one match, use that.  */
+             if (match >= 0)
+               {
+                 options[from] = standard_args[match].nargs;
+                 priority[from] = standard_args[match].priority;
+                 /* If --OPTION=VALUE syntax is used,
+                    this option uses just one argv element.  */
+                 if (equals != 0)
+                   options[from] = 0;
+                 from += options[from];
+               }
+           }
+       done: ;
+       }
+    }
+
+  /* Copy the arguments, in order of decreasing priority, to NEW.  */
+  new[0] = argv[0];
+  while (to < argc)
+    {
+      int best = -1;
+      int best_priority = -9999;
+
+      /* Find the highest priority remaining option.
+        If several have equal priority, take the first of them.  */
+      for (from = 1; from < argc; from++)
+       {
+         if (argv[from] != 0 && priority[from] > best_priority)
+           {
+             best_priority = priority[from];
+             best = from;
+           }
+         /* Skip option arguments--they are tied to the options.  */
+         if (options[from] > 0)
+           from += options[from];
+       }
+           
+      if (best < 0)
+       abort ();
+
+      /* Copy the highest priority remaining option, with its args, to NEW.  */
+      new[to++] = argv[best];
+      for (i = 0; i < options[best]; i++)
+       new[to++] = argv[best + i + 1];
+
+      /* Clear out this option in ARGV.  */
+      argv[best] = 0;
+      for (i = 0; i < options[best]; i++)
+       argv[best + i + 1] = 0;
+    }
+
+  bcopy (new, argv, sizeof (char *) * argc);
+}
+\f
 DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
   "Exit the Emacs job and kill it.\n\
 If ARG is an integer, return ARG as the exit program code.\n\
@@ -797,7 +1164,13 @@ all of which are called before Emacs is actually killed.")
 
   shut_down_emacs (0, 0, STRINGP (arg) ? arg : Qnil);
 
-  exit ((XTYPE (arg) == Lisp_Int) ? XINT (arg)
+  /* If we have an auto-save list file,
+     kill it because we are exiting Emacs deliberately (not crashing).
+     Do it after shut_down_emacs, which does an auto-save.  */
+  if (STRINGP (Vauto_save_list_file_name))
+    unlink (XSTRING (Vauto_save_list_file_name)->data);
+
+  exit (INTEGERP (arg) ? XINT (arg)
 #ifdef VMS
        : 1
 #else
@@ -860,10 +1233,16 @@ shut_down_emacs (sig, no_x, stuff)
   kill_vms_processes ();
 #endif
 
+#if 0 /* This triggers a bug in XCloseDisplay and is not needed.  */
 #ifdef HAVE_X_WINDOWS
-  if (!noninteractive && EQ (Vwindow_system, intern ("x")) && ! no_x)
+  /* It's not safe to call intern here.  Maybe we are crashing.  */
+  if (!noninteractive && SYMBOLP (Vwindow_system)
+      && XSYMBOL (Vwindow_system)->name->size == 1
+      && XSYMBOL (Vwindow_system)->name->data[0] == 'x'
+      && ! no_x)
     Fx_close_current_connection ();
 #endif /* HAVE_X_WINDOWS */
+#endif
 
 #ifdef SIGIO
   /* There is a tendency for a SIGIO signal to arrive within exit,
@@ -876,22 +1255,20 @@ shut_down_emacs (sig, no_x, stuff)
 
 \f
 #ifndef CANNOT_DUMP
-/* Nothing like this can be implemented on an Apollo.
-   What a loss!  */
 
 #ifdef HAVE_SHM
 
 DEFUN ("dump-emacs-data", Fdump_emacs_data, Sdump_emacs_data, 1, 1, 0,
   "Dump current state of Emacs into data file FILENAME.\n\
 This function exists on systems that use HAVE_SHM.")
-  (intoname)
-     Lisp_Object intoname;
+  (filename)
+     Lisp_Object filename;
 {
-  extern int my_edata;
+  extern char my_edata[];
   Lisp_Object tem;
 
-  CHECK_STRING (intoname, 0);
-  intoname = Fexpand_file_name (intoname, Qnil);
+  CHECK_STRING (filename, 0);
+  filename = Fexpand_file_name (filename, Qnil);
 
   tem = Vpurify_flag;
   Vpurify_flag = Qnil;
@@ -900,9 +1277,9 @@ This function exists on systems that use HAVE_SHM.")
   /* 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);
+  memory_warnings (my_edata, malloc_warning);
 #endif
-  map_out_data (XSTRING (intoname)->data);
+  map_out_data (XSTRING (filename)->data);
 
   Vpurify_flag = tem;
 
@@ -919,19 +1296,19 @@ This is used in the file `loadup.el' when building Emacs.\n\
 Bind `command-line-processed' to nil before dumping,\n\
 if you want the dumped Emacs to process its command line\n\
 and announce itself normally when it is run.")
-  (intoname, symname)
-     Lisp_Object intoname, symname;
+  (filename, symfile)
+     Lisp_Object filename, symfile;
 {
-  extern int my_edata;
+  extern char my_edata[];
   Lisp_Object tem;
 
-  CHECK_STRING (intoname, 0);
-  intoname = Fexpand_file_name (intoname, Qnil);
-  if (!NILP (symname))
+  CHECK_STRING (filename, 0);
+  filename = Fexpand_file_name (filename, Qnil);
+  if (!NILP (symfile))
     {
-      CHECK_STRING (symname, 0);
-      if (XSTRING (symname)->size)
-       symname = Fexpand_file_name (symname, Qnil);
+      CHECK_STRING (symfile, 0);
+      if (XSTRING (symfile)->size)
+       symfile = Fexpand_file_name (symfile, Qnil);
     }
 
   tem = Vpurify_flag;
@@ -939,15 +1316,19 @@ and announce itself normally when it is run.")
 
   fflush (stdout);
 #ifdef VMS
-  mapout_data (XSTRING (intoname)->data);
+  mapout_data (XSTRING (filename)->data);
 #else
   /* 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);
+#ifndef WINDOWSNT
+  /* On Windows, this was done before dumping, and that once suffices.
+     Meanwhile, my_edata is not valid on Windows.  */
+  memory_warnings (my_edata, malloc_warning);
+#endif /* not WINDOWSNT */
 #endif
-  unexec (XSTRING (intoname)->data,
-         !NILP (symname) ? XSTRING (symname)->data : 0, &my_edata, 0, 0);
+  unexec (XSTRING (filename)->data,
+         !NILP (symfile) ? XSTRING (symfile)->data : 0, my_edata, 0, 0);
 #endif /* not VMS */
 
   Vpurify_flag = tem;
@@ -985,7 +1366,8 @@ decode_env_path (evarname, defalt)
     {
       p = index (path, SEPCHAR);
       if (!p) p = path + strlen (path);
-      lpath = Fcons (p - path ? make_string (path, p - path) : Qnil,
+      lpath = Fcons (p - path ? make_string (path, p - path)
+                    : build_string ("."),
                     lpath);
       if (*p)
        path = p + 1;
@@ -1019,7 +1401,11 @@ syms_of_emacs ()
 
   DEFVAR_LISP ("system-configuration", &Vsystem_configuration,
     "Value is string indicating configuration Emacs was built for.");
-  Vsystem_configuration = build_string (CONFIGURATION);
+  Vsystem_configuration = build_string (EMACS_CONFIGURATION);
+
+  DEFVAR_LISP ("system-configuration-options", &Vsystem_configuration_options,
+    "String containing the configuration options Emacs was built with.");
+  Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS);
 
   DEFVAR_BOOL ("noninteractive", &noninteractive1,
     "Non-nil means Emacs is running without interactive terminal.");
@@ -1028,20 +1414,31 @@ syms_of_emacs ()
     "Hook to be run whenever kill-emacs is called.\n\
 Since kill-emacs may be invoked when the terminal is disconnected (or\n\
 in other similar situations), functions placed on this hook should not\n\
-expect to be able to interact with the user.");
+expect to be able to interact with the user.  To ask for confirmation,\n\
+see `kill-emacs-query-functions' instead.");
   Vkill_emacs_hook = Qnil;
 
   DEFVAR_INT ("emacs-priority", &emacs_priority,
     "Priority for Emacs to run at.\n\
 This value is effective only if set before Emacs is dumped,\n\
 and only if the Emacs executable is installed with setuid to permit\n\
-it to change priority.  (Emacs sets its uid back to the real uid.)");
+it to change priority.  (Emacs sets its uid back to the real uid.)\n\
+Currently, you need to define SET_EMACS_PRIORITY in `config.h'\n\
+before you compile Emacs, to enable the code for this feature.");
   emacs_priority = 0;
 
-  staticpro (&Vinstallation_directory);
-  Vinstallation_directory = Qnil;
+  DEFVAR_LISP ("invocation-name", &Vinvocation_name,
+    "The program name that was used to run Emacs.\n\
+Any directory names are omitted.");
 
-  /* These have already been set, in init_cmdargs, so don't set them here.  */
-  staticpro (&Vinvocation_name);
-  staticpro (&Vinvocation_directory);
+  DEFVAR_LISP ("invocation-directory", &Vinvocation_directory,
+    "The directory in which the Emacs executable was found, to run it.\n\
+The value is nil if that directory's name is not known.");
+
+  DEFVAR_LISP ("installation-directory", &Vinstallation_directory,
+    "A directory within which to look for the `lib-src' and `etc' directories.\n\
+This is non-nil when we can't find those directories in their standard\n\
+installed locations, but we can find them\n\
+near where the Emacs executable was found.");
+  Vinstallation_directory = Qnil;
 }