#include <signal.h>
#include <errno.h>
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#ifdef VMS
#include <ssdef.h>
#endif
#ifdef BSD_SYSTEM
#include <sys/ioctl.h>
#endif
#include "lisp.h"
#include "commands.h"
#include "intervals.h"
#include "buffer.h"
#include "systty.h"
#include "blockinput.h"
#include "syssignal.h"
#include "process.h"
#include "termhooks.h"
#include "keyboard.h"
#ifdef HAVE_SETRLIMIT
#include <sys/time.h>
#include <sys/resource.h>
#endif
#ifdef HAVE_SETPGID
#if !defined (USG) || defined (BSD_PGRPS)
#define setpgrp setpgid
#endif
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
extern void malloc_warning ();
extern void set_time_zone_rule ();
extern char *index ();
extern char *strerror ();
Lisp_Object Vcommand_line_args;
Lisp_Object Vinvocation_name;
Lisp_Object Vinvocation_directory;
Lisp_Object Vinstallation_directory;
Lisp_Object Vkill_emacs_hook;
#ifdef SIGUSR1
Lisp_Object Vsignal_USR1_hook;
#ifdef SIGUSR2
Lisp_Object Vsignal_USR2_hook;
#endif
#endif
Lisp_Object Vpath_separator;
int initialized;
#ifdef DOUG_LEA_MALLOC
void *malloc_state_ptr;
extern void *malloc_get_state ();
extern void malloc_set_state ();
int malloc_using_checking;
#endif
Lisp_Object Vsystem_type;
Lisp_Object Vsystem_configuration;
Lisp_Object Vsystem_configuration_options;
Lisp_Object Qfile_name_handler_alist;
int inhibit_window_system;
int emacs_priority;
int running_asynch_code;
#ifdef BSD_PGRPS
extern int inherited_pgroup;
#endif
#ifdef HAVE_X_WINDOWS
int display_arg;
#endif
char *stack_bottom;
#ifdef HAVE_WINDOW_SYSTEM
extern Lisp_Object Vwindow_system;
#endif
extern Lisp_Object Vauto_save_list_file_name;
#ifdef USG_SHARED_LIBRARIES
unsigned int bss_end = 0;
#endif
int noninteractive;
int noninteractive1;
char **initial_argv;
int initial_argc;
static void sort_args ();
void syms_of_emacs ();
int fatal_error_code;
int fatal_error_in_progress;
#ifdef SIGUSR1
SIGTYPE
handle_USR1_signal (sig)
int sig;
{
struct input_event buf;
buf.kind = user_signal;
buf.code = 0;
buf.frame_or_window = Fselected_frame ();
buf.modifiers = 0;
buf.timestamp = 0;
kbd_buffer_store_event (&buf);
}
#endif
#ifdef SIGUSR2
SIGTYPE
handle_USR2_signal (sig)
int sig;
{
struct input_event buf;
buf.kind = user_signal;
buf.code = 1;
buf.frame_or_window = Fselected_frame ();
buf.modifiers = 0;
buf.timestamp = 0;
kbd_buffer_store_event (&buf);
}
#endif
SIGTYPE
fatal_error_signal (sig)
int sig;
{
fatal_error_code = sig;
signal (sig, SIG_DFL);
TOTALLY_UNBLOCK_INPUT;
if (! fatal_error_in_progress)
{
fatal_error_in_progress = 1;
shut_down_emacs (sig, 0, Qnil);
}
#ifdef VMS
LIB$STOP (SS$_ABORT);
#else
#ifndef MSDOS
sigunblock (sigmask (fatal_error_code));
#endif
kill (getpid (), fatal_error_code);
#endif
}
#ifdef SIGDANGER
SIGTYPE
memory_warning_signal (sig)
int sig;
{
signal (sig, memory_warning_signal);
malloc_warning ("Operating system warns that virtual memory is running low.\n");
force_auto_save_soon ();
}
#endif
#ifdef __APPLE_CC__
__private_extern__
#endif
#if ! defined (DOS_NT) && ! defined (NO_ABORT)
void
abort ()
{
kill (getpid (), SIGABRT);
exit (1);
}
#endif
static void
init_cmdargs (argc, argv, skip_args)
int argc;
char **argv;
int skip_args;
{
register int i;
Lisp_Object name, dir, tem;
int count = specpdl_ptr - specpdl;
Lisp_Object raw_name;
initial_argv = argv;
initial_argc = argc;
raw_name = build_string (argv[0]);
tem = Ffind_file_name_handler (raw_name, Qt);
if (! NILP (tem))
raw_name = concat2 (build_string ("/:"), raw_name);
Vinvocation_name = Ffile_name_nondirectory (raw_name);
Vinvocation_directory = Ffile_name_directory (raw_name);
if (NILP (Vinvocation_directory))
{
Lisp_Object found;
int yes = openp (Vexec_path, Vinvocation_name,
EXEC_SUFFIXES, &found, 1);
if (yes == 1)
{
tem = Ffind_file_name_handler (found, Qt);
if (! NILP (tem))
found = concat2 (build_string ("/:"), found);
Vinvocation_directory = Ffile_name_directory (found);
}
}
if (!NILP (Vinvocation_directory)
&& NILP (Ffile_name_absolute_p (Vinvocation_directory)))
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;
tem = Fexpand_file_name (build_string ("lib-src"), dir);
lib_src_exists = Ffile_exists_p (tem);
#ifdef MSDOS
tem = Fexpand_file_name (build_string ("info"), dir);
info_exists = Ffile_exists_p (tem);
#else
info_exists = Qnil;
#endif
if (!NILP (lib_src_exists) || !NILP (info_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;
}
}
tem = Fexpand_file_name (build_string ("../lib-src"), dir);
lib_src_exists = Ffile_exists_p (tem);
#ifdef MSDOS
tem = Fexpand_file_name (build_string ("../info"), dir);
info_exists = Ffile_exists_p (tem);
#else
info_exists = Qnil;
#endif
if (!NILP (lib_src_exists) || !NILP (info_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;
}
}
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--)
{
if (i == 0 || i > skip_args)
Vcommand_line_args
= Fcons (build_string (argv[i]), Vcommand_line_args);
}
unbind_to (count, Qnil);
}
DEFUN ("invocation-name", Finvocation_name, Sinvocation_name, 0, 0, 0,
"Return the program name that was used to run Emacs.\n\
Any directory names are omitted.")
()
{
return Fcopy_sequence (Vinvocation_name);
}
DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
0, 0, 0,
"Return the directory name in which the Emacs executable was located")
()
{
return Fcopy_sequence (Vinvocation_directory);
}
#ifdef VMS
#ifdef LINK_CRTL_SHARE
#ifdef SHARABLE_LIB_BUG
extern noshare char **environ;
#endif
#endif
#endif
#ifdef HAVE_TZSET
static char dump_tz[] = "UtC0";
#endif
#ifndef ORDINARY_LINK
#ifdef __GNUC__
#ifndef GCC_CTORS_IN_LIBC
void __do_global_ctors ()
{}
void __do_global_ctors_aux ()
{}
void __do_global_dtors ()
{}
#ifndef LINUX
char * __CTOR_LIST__[2] = { (char *) (-1), 0 };
#endif
char * __DTOR_LIST__[2] = { (char *) (-1), 0 };
#endif
void __main ()
{}
#endif
#endif
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;
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;
}
}
#ifdef DOUG_LEA_MALLOC
static void
malloc_initialize_hook ()
{
extern char **environ;
if (initialized)
{
if (!malloc_using_checking)
{
char **p;
for (p = environ; *p; p++)
if (strncmp (*p, "MALLOC_CHECK_=", 14) == 0)
{
do
*p = p[1];
while (*++p);
break;
}
}
malloc_set_state (malloc_state_ptr);
free (malloc_state_ptr);
}
else
malloc_using_checking = getenv ("MALLOC_CHECK_") != NULL;
}
void (*__malloc_initialize_hook) () = malloc_initialize_hook;
#endif
int
main (argc, argv, envp)
int argc;
char **argv;
char **envp;
{
char stack_bottom_variable;
int skip_args = 0;
extern int errno;
extern int sys_nerr;
#ifdef HAVE_SETRLIMIT
struct rlimit rlim;
#endif
int no_loadup = 0;
#ifdef LINUX_SBRK_BUG
__sbrk (1);
#endif
#ifdef RUN_TIME_REMAP
if (initialized)
run_time_remap (argv[0]);
#endif
sort_args (argc, argv);
argc = 0;
while (argv[argc]) argc++;
if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args)
&& initialized)
{
Lisp_Object tem;
tem = Fsymbol_value (intern ("emacs-version"));
if (!STRINGP (tem))
{
fprintf (stderr, "Invalid value of `emacs-version'\n");
exit (1);
}
else
{
printf ("GNU Emacs %s\n", XSTRING (tem)->data);
printf ("Copyright (C) 1999 Free Software Foundation, Inc.\n");
printf ("GNU Emacs comes with ABSOLUTELY NO WARRANTY.\n");
printf ("You may redistribute copies of Emacs\n");
printf ("under the terms of the GNU General Public License.\n");
printf ("For more information about these matters, ");
printf ("see the file named COPYING.\n");
exit (0);
}
}
#ifdef HAVE_SHM
if (argmatch (argv, argc, "-nl", "--no-shared-memory", 6, NULL, &skip_args))
{
map_in_data (0);
skip_args = 1;
}
else
{
map_in_data (1);
skip_args = 0;
}
#endif
#if defined(NeXT) || defined(RHAPSODY) || defined(DARWIN)
{
extern int malloc_cookie;
if (initialized)
if (malloc_jumpstart (malloc_cookie) != 0)
printf ("malloc jumpstart failed!\n");
}
#endif
#ifdef VMS
{
char *file;
if (argmatch (argv, argc, "-map", "--map-data", 3, &mapin_file, &skip_args))
mapin_data (file);
}
#ifdef LINK_CRTL_SHARE
#ifdef SHARABLE_LIB_BUG
if (!stdin)
stdin = fdopen (0, "r");
if (!stdout)
stdout = fdopen (1, "w");
if (!stderr)
stderr = fdopen (2, "w");
if (!environ)
environ = envp;
#endif
#endif
#endif
#if defined (HAVE_SETRLIMIT) && defined (RLIMIT_STACK)
if (1
#ifndef CANNOT_DUMP
&& (!noninteractive || initialized)
#endif
&& !getrlimit (RLIMIT_STACK, &rlim))
{
long newlim;
extern int re_max_failures;
int ratio = 20 * sizeof (char *);
ratio += ratio / 3;
newlim = re_max_failures * ratio + 200000;
#ifdef __NetBSD__
newlim = (newlim + getpagesize () - 1) / getpagesize () * getpagesize();
#endif
if (newlim > rlim.rlim_max)
{
newlim = rlim.rlim_max;
re_max_failures = (newlim - 200000) / ratio;
}
if (rlim.rlim_cur < newlim)
rlim.rlim_cur = newlim;
setrlimit (RLIMIT_STACK, &rlim);
}
#endif
stack_bottom = &stack_bottom_variable;
#ifdef USG_SHARED_LIBRARIES
if (bss_end)
brk ((void *)bss_end);
#endif
clearerr (stdin);
#ifndef SYSTEM_MALLOC
memory_warnings (0, malloc_warning);
free (realloc (malloc (4), 4));
uninterrupt_malloc ();
#endif
#ifdef MSDOS
_fmode = O_BINARY;
#if __DJGPP__ >= 2
if (!isatty (fileno (stdin)))
setmode (fileno (stdin), O_BINARY);
if (!isatty (fileno (stdout)))
{
fflush (stdout);
setmode (fileno (stdout), O_BINARY);
}
#else
(stdin)->_flag &= ~_IOTEXT;
(stdout)->_flag &= ~_IOTEXT;
(stderr)->_flag &= ~_IOTEXT;
#endif
#endif
#ifdef SET_EMACS_PRIORITY
if (emacs_priority)
nice (emacs_priority);
setuid (getuid ());
#endif
#ifdef EXTRA_INITIALIZE
EXTRA_INITIALIZE;
#endif
inhibit_window_system = 0;
while (1)
{
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;
#endif
}
else
break;
}
if (argmatch (argv, argc, "-nw", "--no-windows", 6, NULL, &skip_args))
inhibit_window_system = 1;
noninteractive = 0;
if (argmatch (argv, argc, "-batch", "--batch", 5, NULL, &skip_args))
noninteractive = 1;
if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args))
{
printf ("\
Usage: %s [--batch] [-t term] [--terminal term]\n\
[-d display] [--display display] [-nw] [--no-windows]\n\
[-q] [--no-init-file] [-u user] [--user user] [--debug-init]\n\
[--unibyte] [--multibyte] [--version] [--no-site-file]\n\
[-f func] [--funcall func] [-l file] [--load file] [--eval expr]\n\
[--insert file] [+linenum] file-to-visit [--kill]\n\
Report bugs to bug-gnu-emacs@gnu.org. First, please see\n\
the Bugs section of the Emacs manual or the file BUGS.\n", argv[0]);
exit (0);
}
if (! noninteractive)
{
#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
init_signals ();
#endif
if (1
#ifndef CANNOT_DUMP
&& initialized
#endif
)
{
sigblock (sigmask (SIGHUP));
if (! noninteractive
|| signal (SIGHUP, SIG_IGN) != SIG_IGN)
signal (SIGHUP, fatal_error_signal);
sigunblock (sigmask (SIGHUP));
}
if (
#ifndef CANNOT_DUMP
! noninteractive || initialized
#else
1
#endif
)
{
signal (SIGQUIT, fatal_error_signal);
signal (SIGILL, fatal_error_signal);
signal (SIGTRAP, fatal_error_signal);
#ifdef SIGUSR1
signal (SIGUSR1, handle_USR1_signal);
#ifdef SIGUSR2
signal (SIGUSR2, handle_USR2_signal);
#endif
#endif
#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
signal (SIGIOT, fatal_error_signal);
#endif
#ifdef SIGEMT
signal (SIGEMT, fatal_error_signal);
#endif
signal (SIGFPE, fatal_error_signal);
#ifdef SIGBUS
signal (SIGBUS, fatal_error_signal);
#endif
signal (SIGSEGV, fatal_error_signal);
#ifdef SIGSYS
signal (SIGSYS, fatal_error_signal);
#endif
signal (SIGTERM, fatal_error_signal);
#ifdef SIGXCPU
signal (SIGXCPU, fatal_error_signal);
#endif
#ifdef SIGXFSZ
signal (SIGXFSZ, fatal_error_signal);
#endif
#ifdef SIGDANGER
signal (SIGDANGER, memory_warning_signal);
#endif
#ifdef AIX
signal (SIGXCPU, fatal_error_signal);
#ifndef _I386
signal (SIGIOINT, fatal_error_signal);
#endif
signal (SIGGRANT, fatal_error_signal);
signal (SIGRETRACT, fatal_error_signal);
signal (SIGSOUND, fatal_error_signal);
signal (SIGMSG, fatal_error_signal);
#endif
}
noninteractive1 = noninteractive;
if (!initialized)
{
init_alloc_once ();
init_obarray ();
init_eval_once ();
init_charset_once ();
init_coding_once ();
init_syntax_once ();
init_category_once ();
init_casetab_once ();
init_buffer_once ();
init_minibuf_once ();
init_window_once ();
init_fileio_once ();
}
init_alloc ();
init_eval ();
init_coding ();
init_data ();
#ifdef CLASH_DETECTION
init_filelock ();;
#endif
running_asynch_code = 0;
if (
#ifndef CANNOT_DUMP
! noninteractive || initialized
#else
1
#endif
)
{
int inhibit_unibyte = 0;
if (argmatch (argv, argc, "-no-unibyte", "--no-unibyte", 4, NULL, &skip_args)
|| argmatch (argv, argc, "-multibyte", "--multibyte", 4, NULL, &skip_args))
inhibit_unibyte = 1;
if (argmatch (argv, argc, "-unibyte", "--unibyte", 4, NULL, &skip_args)
|| argmatch (argv, argc, "-no-multibyte", "--no-multibyte", 4, NULL, &skip_args)
|| (getenv ("EMACS_UNIBYTE") && !inhibit_unibyte))
{
Lisp_Object old_log_max;
Lisp_Object symbol, tail;
symbol = intern ("default-enable-multibyte-characters");
Fset (symbol, Qnil);
if (initialized)
{
old_log_max = Vmessage_log_max;
XSETFASTINT (Vmessage_log_max, 0);
message_dolog ("", 0, 1, 0);
Vmessage_log_max = old_log_max;
}
for (tail = Vbuffer_alist; CONSP (tail);
tail = XCONS (tail)->cdr)
{
Lisp_Object buffer;
buffer = Fcdr (XCONS (tail)->car);
if (BUF_Z (XBUFFER (buffer)) > BUF_BEG (XBUFFER (buffer)))
abort ();
XBUFFER (buffer)->enable_multibyte_characters = Qnil;
}
}
}
no_loadup
= !argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args);
#ifdef HAVE_X_WINDOWS
{
char *displayname = 0;
int i;
int count_before = skip_args;
while (1)
{
int count_before_this = 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;
else
break;
count_before = count_before_this;
}
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++;
}
else if (displayname != 0 && skip_args > count_before
&& argv[count_before + 1][1] == '-')
argv[count_before + 1] = "-d";
skip_args = count_before;
}
#endif
#ifdef MSDOS
init_dosfns ();
if (initialized)
init_environment (argc, argv, skip_args);
else
tzset ();
#endif
#ifdef WINDOWSNT
init_environment (argv);
init_ntproc ();
#endif
set_process_environment ();
#ifdef AIX3_2
putenv ("LANG=C");
#endif
init_buffer ();
init_callproc_1 ();
init_cmdargs (argc, argv, skip_args);
if (initialized)
{
Lisp_Object old_log_max;
old_log_max = Vmessage_log_max;
XSETFASTINT (Vmessage_log_max, 0);
message_dolog ("", 0, 1, 0);
Vmessage_log_max = old_log_max;
}
init_callproc ();
init_lread ();
if (!initialized)
{
syms_of_data ();
syms_of_alloc ();
syms_of_lread ();
syms_of_print ();
syms_of_eval ();
syms_of_fns ();
syms_of_floatfns ();
syms_of_abbrev ();
syms_of_buffer ();
syms_of_bytecode ();
syms_of_callint ();
syms_of_casefiddle ();
syms_of_casetab ();
syms_of_callproc ();
syms_of_category ();
syms_of_ccl ();
syms_of_charset ();
syms_of_cmds ();
#ifndef NO_DIR_LIBRARY
syms_of_dired ();
#endif
syms_of_display ();
syms_of_doc ();
syms_of_editfns ();
syms_of_emacs ();
syms_of_fileio ();
syms_of_coding ();
#ifdef CLASH_DETECTION
syms_of_filelock ();
#endif
syms_of_indent ();
syms_of_insdel ();
syms_of_keyboard ();
syms_of_keymap ();
syms_of_macros ();
syms_of_marker ();
syms_of_minibuf ();
syms_of_mocklisp ();
syms_of_process ();
syms_of_search ();
syms_of_frame ();
syms_of_syntax ();
syms_of_term ();
syms_of_undo ();
syms_of_textprop ();
#ifdef VMS
syms_of_vmsproc ();
#endif
#ifdef WINDOWSNT
syms_of_ntproc ();
#endif
syms_of_window ();
syms_of_xdisp ();
#ifdef HAVE_X_WINDOWS
syms_of_xterm ();
syms_of_xfns ();
syms_of_fontset ();
#ifdef HAVE_X11
syms_of_xselect ();
#endif
#endif
#ifndef HAVE_NTGUI
syms_of_xfaces ();
syms_of_xmenu ();
#endif
#ifdef HAVE_NTGUI
syms_of_w32term ();
syms_of_w32fns ();
syms_of_w32faces ();
syms_of_w32select ();
syms_of_w32menu ();
syms_of_fontset ();
#endif
#ifdef SYMS_SYSTEM
SYMS_SYSTEM;
#endif
#ifdef SYMS_MACHINE
SYMS_MACHINE;
#endif
keys_of_casefiddle ();
keys_of_cmds ();
keys_of_buffer ();
keys_of_keyboard ();
keys_of_keymap ();
keys_of_macros ();
keys_of_minibuf ();
keys_of_window ();
keys_of_frame ();
}
if (!noninteractive)
{
#ifdef VMS
init_vms_input ();
#endif
init_display ();
}
init_keyboard ();
#ifdef VMS
init_vmsproc ();
#endif
init_sys_modes ();
init_xdisp ();
init_macros ();
init_editfns ();
#ifdef LISP_FLOAT_TYPE
init_floatfns ();
#endif
#ifdef VMS
init_vmsfns ();
#endif
init_emacs_process ();
if (!initialized)
{
char *file;
if (argmatch (argv, argc, "-l", "--load", 3, &file, &skip_args))
Vtop_level = Fcons (intern ("load"),
Fcons (build_string (file), Qnil));
#ifdef CANNOT_DUMP
if (! no_loadup)
Vtop_level = Fcons (intern ("load"),
Fcons (build_string ("loadup.el"), Qnil));
#endif
}
if (initialized)
{
#ifdef HAVE_TZSET
{
char *tz = getenv ("TZ");
if (tz && !strcmp (tz, dump_tz))
{
++*tz;
tzset ();
--*tz;
}
}
#endif
}
#ifdef __FreeBSD__
#ifdef PROFILING
if (initialized)
{
extern void _mcleanup ();
extern char etext;
extern Lisp_Object Fredraw_frame ();
atexit (_mcleanup);
monstartup (Fredraw_frame, &etext);
}
else
moncontrol (0);
#endif
#endif
initialized = 1;
#ifdef LOCALTIME_CACHE
tzset ();
#endif
Frecursive_edit ();
}
struct standard_args
{
char *name;
char *longname;
int priority;
int nargs;
};
struct standard_args standard_args[] =
{
{ "-version", "--version", 150, 0 },
#ifdef HAVE_SHM
{ "-nl", "--no-shared-memory", 140, 0 },
#endif
#ifdef VMS
{ "-map", "--map-data", 130, 0 },
#endif
{ "-t", "--terminal", 120, 1 },
{ "-nw", "--no-windows", 110, 0 },
{ "-batch", "--batch", 100, 0 },
{ "-help", "--help", 90, 0 },
{ "-no-unibyte", "--no-unibyte", 83, 0 },
{ "-multibyte", "--multibyte", 82, 0 },
{ "-unibyte", "--unibyte", 81, 0 },
{ "-no-multibyte", "--no-multibyte", 80, 0 },
#ifdef CANNOT_DUMP
{ "-nl", "--no-loadup", 70, 0 },
#endif
{ "-d", "--display", 60, 1 },
{ "-display", 0, 60, 1 },
{ "-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 },
{ "-title", 0, 10, 1 },
{ "-name", "--name", 10, 1 },
{ "-xrm", "--xrm", 10, 1 },
{ "-r", "--reverse-video", 5, 0 },
{ "-rv", 0, 5, 0 },
{ "-reverse", 0, 5, 0 },
{ "-hb", "--horizontal-scroll-bars", 5, 0 },
{ "-vb", "--vertical-scroll-bars", 5, 0 },
{ "-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 },
{ "-find-file", "--find-file", 0, 1 },
{ "-visit", "--visit", 0, 1 },
{ "-insert", "--insert", 0, 1 },
{ "-kill", "--kill", -10, 0 },
};
static void
sort_args (argc, argv)
int argc;
char **argv;
{
char **new = (char **) xmalloc (sizeof (char *) * argc);
int *options = (int *) xmalloc (sizeof (int) * argc);
int *priority = (int *) xmalloc (sizeof (int) * argc);
int to = 1;
int incoming_used = 1;
int from;
int i;
int end_of_options = argc;
for (from = 1; from < argc; from++)
{
options[from] = -1;
priority[from] = 0;
if (argv[from][0] == '-')
{
int match, thislen;
char *equals;
if (argv[from][1] == '-' && argv[from][2] == 0)
{
for (; from < argc; from++)
{
priority[from] = -100;
options[from] = -1;
}
break;
}
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;
if (from + standard_args[i].nargs >= argc)
fatal ("Option `%s' requires an argument\n", argv[from]);
from += standard_args[i].nargs;
goto done;
}
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 (match >= 0)
{
options[from] = standard_args[match].nargs;
priority[from] = standard_args[match].priority;
if (equals != 0)
options[from] = 0;
if (from + options[from] >= argc)
fatal ("Option `%s' requires an argument\n", argv[from]);
from += options[from];
}
}
done: ;
}
}
new[0] = argv[0];
while (incoming_used < argc)
{
int best = -1;
int best_priority = -9999;
for (from = 1; from < argc; from++)
{
if (argv[from] != 0 && priority[from] > best_priority)
{
best_priority = priority[from];
best = from;
}
if (options[from] > 0)
from += options[from];
}
if (best < 0)
abort ();
if (! (options[best] == 0
&& ! strcmp (new[to - 1], argv[best])))
{
new[to++] = argv[best];
for (i = 0; i < options[best]; i++)
new[to++] = argv[best + i + 1];
}
incoming_used += 1 + (options[best] > 0 ? options[best] : 0);
argv[best] = 0;
for (i = 0; i < options[best]; i++)
argv[best + i + 1] = 0;
}
while (to < argc)
new[to++] = 0;
bcopy (new, argv, sizeof (char *) * argc);
free (options);
free (new);
free (priority);
}
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\
If ARG is a string, stuff it as keyboard input.\n\n\
The value of `kill-emacs-hook', if not void,\n\
is a list of functions (of no args),\n\
all of which are called before Emacs is actually killed.")
(arg)
Lisp_Object arg;
{
Lisp_Object hook, hook1;
int i;
struct gcpro gcpro1;
GCPRO1 (arg);
if (feof (stdin))
arg = Qt;
if (!NILP (Vrun_hooks) && !noninteractive)
call1 (Vrun_hooks, intern ("kill-emacs-hook"));
UNGCPRO;
shut_down_emacs (0, 0, STRINGP (arg) ? arg : Qnil);
if (STRINGP (Vauto_save_list_file_name))
unlink (XSTRING (Vauto_save_list_file_name)->data);
exit (INTEGERP (arg) ? XINT (arg)
#ifdef VMS
: 1
#else
: 0
#endif
);
}
void
shut_down_emacs (sig, no_x, stuff)
int sig, no_x;
Lisp_Object stuff;
{
Vrun_hooks = Qnil;
#ifdef EMACS_HAVE_TTY_PGRP
{
int pgrp = EMACS_GETPGRP (0);
int tpgrp;
if (EMACS_GET_TTY_PGRP (0, &tpgrp) != -1
&& tpgrp == pgrp)
{
fflush (stdout);
reset_sys_modes ();
if (sig && sig != SIGTERM)
fprintf (stderr, "Fatal error (%d).", sig);
}
}
#else
fflush (stdout);
reset_sys_modes ();
#endif
stuff_buffered_input (stuff);
kill_buffer_processes (Qnil);
Fdo_auto_save (Qt, Qnil);
#ifdef CLASH_DETECTION
unlock_all_files ();
#endif
#ifdef VMS
kill_vms_processes ();
#endif
#if 0
#ifdef HAVE_X_WINDOWS
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
#endif
#ifdef SIGIO
unrequest_sigio ();
signal (SIGIO, SIG_IGN);
#endif
#ifdef WINDOWSNT
term_ntproc ();
#endif
#ifdef MSDOS
dos_cleanup ();
#endif
}
#ifndef CANNOT_DUMP
#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.")
(filename)
Lisp_Object filename;
{
extern char my_edata[];
Lisp_Object tem;
CHECK_STRING (filename, 0);
filename = Fexpand_file_name (filename, Qnil);
tem = Vpurify_flag;
Vpurify_flag = Qnil;
fflush (stdout);
#ifndef SYSTEM_MALLOC
memory_warnings (my_edata, malloc_warning);
#endif
map_out_data (XSTRING (filename)->data);
Vpurify_flag = tem;
return Qnil;
}
#else
DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0,
"Dump current state of Emacs into executable file FILENAME.\n\
Take symbols from SYMFILE (presumably the file you executed to run Emacs).\n\
This is used in the file `loadup.el' when building Emacs.\n\
\n\
You must run Emacs in batch mode in order to dump it.")
(filename, symfile)
Lisp_Object filename, symfile;
{
extern char my_edata[];
Lisp_Object tem;
Lisp_Object symbol;
int count = specpdl_ptr - specpdl;
if (! noninteractive)
error ("Dumping Emacs works only in batch mode");
symbol = intern ("command-line-process");
specbind (symbol, Qnil);
CHECK_STRING (filename, 0);
filename = Fexpand_file_name (filename, Qnil);
if (!NILP (symfile))
{
CHECK_STRING (symfile, 0);
if (XSTRING (symfile)->size)
symfile = Fexpand_file_name (symfile, Qnil);
}
tem = Vpurify_flag;
Vpurify_flag = Qnil;
#ifdef HAVE_TZSET
set_time_zone_rule (dump_tz);
#ifndef LOCALTIME_CACHE
tzset ();
#endif
#endif
fflush (stdout);
#ifdef VMS
mapout_data (XSTRING (filename)->data);
#else
#ifndef SYSTEM_MALLOC
#ifndef WINDOWSNT
memory_warnings (my_edata, malloc_warning);
#endif
#endif
#ifdef DOUG_LEA_MALLOC
malloc_state_ptr = malloc_get_state ();
#endif
unexec (XSTRING (filename)->data,
!NILP (symfile) ? XSTRING (symfile)->data : 0, my_edata, 0, 0);
#ifdef DOUG_LEA_MALLOC
free (malloc_state_ptr);
#endif
#endif
Vpurify_flag = tem;
return unbind_to (count, Qnil);
}
#endif
#endif
#ifndef SEPCHAR
#define SEPCHAR ':'
#endif
Lisp_Object
decode_env_path (evarname, defalt)
char *evarname, *defalt;
{
register char *path, *p;
Lisp_Object lpath, element, tem;
if (evarname != 0)
path = (char *) getenv (evarname);
else
path = 0;
if (!path)
path = defalt;
#ifdef DOS_NT
if (path)
{
p = alloca (strlen (path) + 1);
strcpy (p, path);
path = p;
if ('/' == DIRECTORY_SEP)
dostounix_filename (path);
else
unixtodos_filename (path);
}
#endif
lpath = Qnil;
while (1)
{
p = index (path, SEPCHAR);
if (!p) p = path + strlen (path);
element = (p - path ? make_string (path, p - path)
: build_string ("."));
tem = Ffind_file_name_handler (element, Qt);
if (! NILP (tem))
element = concat2 (build_string ("/:"), element);
lpath = Fcons (element, lpath);
if (*p)
path = p + 1;
else
break;
}
return Fnreverse (lpath);
}
void
syms_of_emacs ()
{
Qfile_name_handler_alist = intern ("file-name-handler-alist");
staticpro (&Qfile_name_handler_alist);
#ifndef CANNOT_DUMP
#ifdef HAVE_SHM
defsubr (&Sdump_emacs_data);
#else
defsubr (&Sdump_emacs);
#endif
#endif
defsubr (&Skill_emacs);
defsubr (&Sinvocation_name);
defsubr (&Sinvocation_directory);
DEFVAR_LISP ("command-line-args", &Vcommand_line_args,
"Args passed by shell to Emacs, as a list of strings.");
DEFVAR_LISP ("system-type", &Vsystem_type,
"Value is symbol indicating type of operating system you are using.");
Vsystem_type = intern (SYSTEM_TYPE);
DEFVAR_LISP ("system-configuration", &Vsystem_configuration,
"Value is string indicating configuration Emacs was built for.");
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.");
DEFVAR_LISP ("kill-emacs-hook", &Vkill_emacs_hook,
"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. To ask for confirmation,\n\
see `kill-emacs-query-functions' instead.");
Vkill_emacs_hook = Qnil;
#ifdef SIGUSR1
DEFVAR_LISP ("signal-USR1-hook", &Vsignal_USR1_hook,
"Hook to be run whenever emacs receives a USR1 signal");
Vsignal_USR1_hook = Qnil;
#ifdef SIGUSR2
DEFVAR_LISP ("signal-USR2-hook", &Vsignal_USR2_hook,
"Hook to be run whenever emacs receives a USR2 signal");
Vsignal_USR2_hook = Qnil;
#endif
#endif
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.)\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;
DEFVAR_LISP ("path-separator", &Vpath_separator,
"The directory separator in search paths, as a string.");
{
char c = SEPCHAR;
Vpath_separator = make_string (&c, 1);
}
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;
}