*** empty log message ***
[bpt/emacs.git] / src / emacs.c
index 2fcb6a8..a943a07 100644 (file)
@@ -84,7 +84,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 +98,7 @@ int inhibit_window_system;
    priority; Those functions have their own extern declaration.  */
 int emacs_priority;
 
-#ifdef BSD
+#ifdef BSD_PGRPS
 /* See sysdep.c.  */
 extern int inherited_pgroup;
 #endif
@@ -128,6 +132,10 @@ int noninteractive;
    but nothing terrible happens if user sets this one.  */
 
 int noninteractive1;
+
+/* Save argv and argc.  */
+char **initial_argv;
+int initial_argc;
 \f
 /* Signal code for the fatal signal that was received */
 int fatal_error_code;
@@ -175,6 +183,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 +200,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
@@ -210,57 +224,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 +265,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
@@ -318,6 +314,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 ()
@@ -329,11 +326,73 @@ __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, sstr, lstr, minlen, valptr, skipptr)
+     char **argv;
+     char *sstr;
+     char *lstr;
+     int minlen;
+     char **valptr;
+     int *skipptr;
+{
+  char *p;
+  int arglen;
+  char *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 (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,7 +406,7 @@ main (argc, argv, envp)
 
 /* Map in shared memory, if we are using that.  */
 #ifdef HAVE_SHM
-  if (argc > 1 && !strcmp (argv[1], "-nl"))
+  if (argmatch (argv, "-nl", "--no-shared-memory", 6, NULL, &skip_args))
     {
       map_in_data (0);
       /* The shared memory was just restored, which clobbered this.  */
@@ -378,6 +437,8 @@ main (argc, argv, envp)
   {
     int i;
 
+    /* We don't check for a long option --display here, since the X code
+       won't be able to recognize that form anyway.  */
     for (i = 1; (i < argc && ! display_arg); i++)
       if (!strcmp (argv[i], "-d") || !strcmp (argv[i], "-display"))
        display_arg = 1;
@@ -386,11 +447,11 @@ main (argc, argv, envp)
 
 #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, "-map", "--map-data", 3, &mapin_file, &skip_args))
+      mapin_data (file);
+  }
 
 #ifdef LINK_CRTL_SHARE
 #ifdef SHAREABLE_LIB_BUG
@@ -422,19 +483,6 @@ main (argc, argv, envp)
 
   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,
@@ -465,53 +513,78 @@ 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]);
+  {
+    char *term;
+    if (argmatch (argv, "-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_X_WINDOWS
-      inhibit_window_system = 1;       /* -t => -nw */
+       inhibit_window_system = 1; /* -t => -nw */
 #endif
-    }
+      }
+  }
+  if (argmatch (argv, "-nw", "--no-windows", 6, NULL, &skip_args))
+    inhibit_window_system = 1;
+
+  /* Handle the -batch switch, which means don't do interactive display.  */
+  noninteractive = 0;
+  if (argmatch (argv, "-batch", "--batch", 5, NULL, &skip_args))
+    noninteractive = 1;
 
-  if (skip_args + 1 < argc
-      && (!strcmp (argv[skip_args + 1], "-nw")))
+  /* Handle the --help option, which gives a usage message..  */
+  if (argmatch (argv, "-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\
+\(Arguments above this line must be first; those below may be in any order)\n\
+      [-f func] [--funcall func]  [-l file] [--load file]  [--insert file]\n\
+      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"))
+  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
@@ -692,6 +765,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 */
@@ -713,6 +787,11 @@ main (argc, argv, envp)
 #endif /* HAVE_X_MENU */
 #endif /* HAVE_X_WINDOWS */
 
+#if defined (MSDOS) && !defined (HAVE_X_WINDOWS)
+      syms_of_xfaces ();
+      syms_of_xmenu ();
+#endif
+
 #ifdef SYMS_SYSTEM
       SYMS_SYSTEM;
 #endif
@@ -734,13 +813,14 @@ 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, "-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, "-nl", "--no-loadup", 6, NULL, &skip_args))
        Vtop_level = Fcons (intern ("load"),
                            Fcons (build_string ("loadup.el"), Qnil));
 #endif /* CANNOT_DUMP */
@@ -757,6 +837,16 @@ main (argc, argv, envp)
   tzset ();
 #endif /* defined (sun) || defined (LOCALTIME_CACHE) */
 
+  /* Handle the GNU standard option --version.  */
+  if (argmatch (argv, "-version", "--version", 3, NULL, &skip_args))
+    {
+      Lisp_Object ver;
+      ver = call0 (intern ("emacs-version"));
+      if (STRINGP (ver))
+       printf ("%s\n", XSTRING (ver)->data);
+      exit (0);
+    }
+
   /* Enter editor command loop.  This never returns.  */
   Frecursive_edit ();
   /* NOTREACHED */
@@ -794,7 +884,7 @@ 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)
+  exit (INTEGERP (arg) ? XINT (arg)
 #ifdef VMS
        : 1
 #else
@@ -857,10 +947,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,
@@ -1016,7 +1112,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.");
@@ -1032,13 +1132,23 @@ expect to be able to interact with the user.");
     "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);
+  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;
-  staticpro (&Vinvocation_name);
-  Vinvocation_name = Qnil;
-  staticpro (&Vinvocation_directory);
-  Vinvocation_directory = Qnil;
 }