]> code.delx.au - gnu-emacs/blobdiff - src/emacs.c
(Fbyte_code): Harmonize arguments with documentation.
[gnu-emacs] / src / emacs.c
index a8952ad2a2817c2ce00d7d10550a1ee63bae55d7..8c669a0fd61ca3ed1255d7cd0dd6aba8c62c0d93 100644 (file)
@@ -1,5 +1,5 @@
 /* Fully extensible Emacs, running on Unix, intended for GNU.
-   Copyright (C) 1985, 1986, 1987, 1993 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"
@@ -53,6 +47,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define O_RDWR 2
 #endif
 
+extern void malloc_warning ();
+extern char *index ();
+extern char *strerror ();
+
 /* Command line args from shell, as list of strings */
 Lisp_Object Vcommand_line_args;
 
@@ -63,6 +61,10 @@ Lisp_Object Vinvocation_name;
 /* The directory name from which Emacs was invoked.  */
 Lisp_Object Vinvocation_directory;
 
+/* The directory name in which to find subdirs such as lisp and etc.
+   nil means get them only from PATH_LOADSEARCH.  */
+Lisp_Object Vinstallation_directory;
+
 /* Hook run by `kill-emacs' before it does really anything.  */
 Lisp_Object Vkill_emacs_hook;
 
@@ -76,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;
@@ -86,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
@@ -100,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
@@ -120,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;
@@ -150,14 +168,16 @@ fatal_error_signal (sig)
      Remember that since we're in a signal handler, the signal we're
      going to send is probably blocked, so we have to unblock it if we
      want to really receive it.  */
+#ifndef MSDOS
   sigunblock (sigmask (fatal_error_code));
+#endif
   kill (getpid (), fatal_error_code);
 #endif /* not VMS */
 }
 
 #ifdef SIGDANGER
 
-/* Handle bus errors, illegal instruction, etc. */
+/* Handler for SIGDANGER.  */
 SIGTYPE
 memory_warning_signal (sig)
      int sig;
@@ -165,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
@@ -177,6 +200,10 @@ init_cmdargs (argc, argv, skip_args)
      int 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]));
@@ -191,6 +218,68 @@ 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))
+    {
+      dir = Vinvocation_directory;
+      name = Fexpand_file_name (Vinvocation_name, dir);
+      while (1)
+       {
+         Lisp_Object tem, lib_src_exists;
+         Lisp_Object etc_exists, info_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 ("etc"), dir);
+             etc_exists = Ffile_exists_p (tem);
+             if (!NILP (etc_exists))
+               {
+                 Vinstallation_directory
+                   = Ffile_name_as_directory (dir);
+                 break;
+               }
+           }
+
+         /* See if dir's parent contains those subdirs.  */
+         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 (".."), dir);
+                 Vinstallation_directory
+                   = Ffile_name_as_directory (tem);
+                 break;
+               }
+           }
+
+         /* If the Emacs executable is actually a link,
+            next try the dir that the link points into.  */
+         tem = Ffile_symlink_p (name);
+         if (!NILP (tem))
+           {
+             name = Fexpand_file_name (tem, dir);
+             dir = Ffile_name_directory (name);
+           }
+         else
+           break;
+       }
+    }
+
   Vcommand_line_args = Qnil;
 
   for (i = argc - 1; i >= 0; i--)
@@ -220,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 */
 
@@ -232,6 +321,7 @@ extern noshare char **environ;
    Provide dummy definitions to avoid error.
    (We don't have any real constructors or destructors.)  */
 #ifdef __GNUC__
+#ifndef GCC_CTORS_IN_LIBC
 __do_global_ctors ()
 {}
 __do_global_ctors_aux ()
@@ -243,11 +333,81 @@ __do_global_dtors ()
 char * __CTOR_LIST__[2] = { (char *) (-1), 0 };
 #endif
 char * __DTOR_LIST__[2] = { (char *) (-1), 0 };
+#endif /* GCC_CTORS_IN_LIBC */
 __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;
@@ -258,12 +418,32 @@ main (argc, argv, envp)
   int skip_args = 0;
   extern int errno;
   extern sys_nerr;
-  extern char *sys_errlist[];
-  extern void malloc_warning ();
+
+#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.  */
@@ -278,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");
@@ -319,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 */
 
@@ -333,28 +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
-  {
-    inherited_pgroup = EMACS_GETPGRP (0);
-    setpgrp (0, getpid ());
-  }
-#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)
     {
@@ -367,58 +517,129 @@ main (argc, argv, envp)
     }
 #endif /* not SYSTEM_MALLOC */
 
-#ifdef PRIO_PROCESS
+#ifdef MSDOS
+  /* We do all file input/output as binary files.  When we need to translate
+     newlines, we do that manually.  */
+  _fmode = O_BINARY;
+  (stdin)->_flag &= ~_IOTEXT;
+  (stdout)->_flag &= ~_IOTEXT;
+  (stderr)->_flag &= ~_IOTEXT;
+#endif /* MSDOS */
+
+#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;
-
-         if (errno >= 0 && errno < sys_nerr)
-           errstring = sys_errlist[errno];
-         else
-           errstring = "undocumented error code";
-         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
@@ -440,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);
@@ -469,17 +711,8 @@ main (argc, argv, envp)
 #endif
 
 #ifdef AIX
-      signal (20, fatal_error_signal);
-      signal (21, fatal_error_signal);
-      signal (22, fatal_error_signal);
-      signal (24, fatal_error_signal);
-#if 0 /* mvn@library.ucla.edu says these are SIGIO on AIX 3.2.4.  */
-      signal (23, fatal_error_signal);
-#ifdef SIGIO
-      signal (SIGAIO, fatal_error_signal);
-      signal (SIGPTY, fatal_error_signal);
-#endif
-#endif
+/* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU.  */
+      signal (SIGXCPU, fatal_error_signal);
 #ifndef _I386
       signal (SIGIOINT, fatal_error_signal);
 #endif
@@ -511,6 +744,20 @@ 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
      many circumstances; it seems flimsy to put off initializing it
@@ -601,6 +848,7 @@ main (argc, argv, envp)
       syms_of_search ();
       syms_of_frame ();
       syms_of_syntax ();
+      syms_of_term ();
       syms_of_undo ();
 
       /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
@@ -617,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
@@ -643,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\
@@ -703,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
@@ -730,6 +1197,9 @@ shut_down_emacs (sig, no_x, stuff)
      int sig, no_x;
      Lisp_Object stuff;
 {
+  /* Prevent running of hooks from now on.  */
+  Vrun_hooks = Qnil;
+
   /* If we are controlling the terminal, reset terminal modes */
 #ifdef EMACS_HAVE_TTY_PGRP
   {
@@ -763,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,
@@ -779,8 +1255,6 @@ 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
 
@@ -790,9 +1264,8 @@ This function exists on systems that use HAVE_SHM.")
   (intoname)
      Lisp_Object intoname;
 {
-  extern int my_edata;
+  extern char my_edata[];
   Lisp_Object tem;
-  extern void malloc_warning ();
 
   CHECK_STRING (intoname, 0);
   intoname = Fexpand_file_name (intoname, Qnil);
@@ -804,7 +1277,7 @@ 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);
 
@@ -826,9 +1299,8 @@ and announce itself normally when it is run.")
   (intoname, symname)
      Lisp_Object intoname, symname;
 {
-  extern int my_edata;
+  extern char my_edata[];
   Lisp_Object tem;
-  extern void malloc_warning ();
 
   CHECK_STRING (intoname, 0);
   intoname = Fexpand_file_name (intoname, Qnil);
@@ -849,10 +1321,14 @@ and announce itself normally when it is run.")
   /* 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);
+         !NILP (symname) ? XSTRING (symname)->data : 0, my_edata, 0, 0);
 #endif /* not VMS */
 
   Vpurify_flag = tem;
@@ -873,7 +1349,6 @@ decode_env_path (evarname, defalt)
      char *evarname, *defalt;
 {
   register char *path, *p;
-  extern char *index ();
 
   Lisp_Object lpath;
 
@@ -891,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;
@@ -925,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.");
@@ -934,18 +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 (&Vinvocation_name);
-  Vinvocation_name = Qnil;
-  staticpro (&Vinvocation_directory);
-  Vinvocation_directory = Qnil;
+  DEFVAR_LISP ("invocation-name", &Vinvocation_name,
+    "The program name that was used to run Emacs.\n\
+Any directory names are omitted.");
+
+  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;
 }