#include <config.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#ifdef VMS
#include <ssdef.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.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_SETLOCALE
#include <locale.h>
#endif
#ifdef HAVE_SETRLIMIT
#include <sys/time.h>
#include <sys/resource.h>
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
#ifdef HAVE_SETPGID
#if !defined (USG) || defined (BSD_PGRPS)
#undef setpgrp
#define setpgrp setpgid
#endif
#endif
extern void malloc_warning P_ ((char *));
extern void set_time_zone_rule P_ ((char *));
#ifdef HAVE_INDEX
extern char *index P_ ((const char *, int));
#endif
EMACS_INT gdb_valbits = VALBITS;
EMACS_INT gdb_gctypebits = GCTYPEBITS;
EMACS_INT gdb_emacs_intbits = sizeof (EMACS_INT) * BITS_PER_CHAR;
#ifdef DATA_SEG_BITS
EMACS_INT gdb_data_seg_bits = DATA_SEG_BITS;
#else
EMACS_INT gdb_data_seg_bits = 0;
#endif
EMACS_INT PVEC_FLAG = PSEUDOVECTOR_FLAG;
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;
Lisp_Object Vsystem_messages_locale;
Lisp_Object Vprevious_system_messages_locale;
Lisp_Object Vsystem_time_locale;
Lisp_Object Vprevious_system_time_locale;
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 ();
#define USAGE1 "\
Usage: %s [OPTION-OR-FILENAME]...\n\
\n\
Run Emacs, the extensible, customizable, self-documenting real-time\n\
display editor. The recommended way to start Emacs for normal editing\n\
is with no options at all.\n\
\n\
Run M-x info RET m emacs RET m command arguments RET inside Emacs to\n\
read the main documentation for these command-line arguments.\n\
\n\
Initialization options:\n\
\n\
--batch do not do interactive display; implies -q\n\
--debug-init enable Emacs Lisp debugger during init file\n\
--help display this help message and exit\n\
--multibyte, --no-unibyte run Emacs in multibyte mode\n\
--no-init-file, -q load neither ~/.emacs nor default.el\n\
--no-shared-memory, -nl do not use shared memory\n\
--no-site-file do not load site-start.el\n\
--no-windows, -nw don't communicate with X, ignoring $DISPLAY\n\
--terminal, -t DEVICE use DEVICE for terminal I/O\n\
--unibyte, --no-multibyte run Emacs in unibyte mode\n\
--user, -u USER load ~USER/.emacs instead of your own\n\
--version display version information and exit\n\
\n\
Action options:\n\
\n\
FILE visit FILE using find-file\n\
+LINE FILE visit FILE using find-file, then go to line LINE\n\
+LINE:COLUMN FILE visit FILE using find-file, then go to line LINE,\n\
column COLUMN\n\
--directory, -L DIR add DIR to variable load-path\n\
--eval EXPR evaluate Emacs Lisp expression EXPR\n\
--execute EXPR evaluate Emacs Lisp expression EXPR\n\
--find-file FILE visit FILE\n\
--funcall, -f FUNC call Emacs function FUNC with no arguments\n\
--insert FILE insert contents of FILE into current buffer\n\
--kill exit without asking for confirmation\n\
--load, -l FILE load FILE of Emacs Lisp code using the load function\n\
--visit FILE visit FILE\n\
\n"
#define USAGE2 "\
Display options:\n\
\n\
--background-color, -bg COLOR window background color\n\
--border-color, -bd COLOR main border color\n\
--border-width, -bw WIDTH width of main border\n\
--cursor-color, -cr COLOR color of the Emacs cursor indicating point\n\
--display, -d DISPLAY use X server DISPLAY\n\
--font, -fn FONT default font; must be fixed-widthp\n\
--foreground-color, -fg COLOR window foreground color\n\
--geometry, -g GEOMETRY window geometry\n\
--iconic start Emacs in iconified state\n\
--icon-type, -i use picture of gnu for Emacs icon\n\
--internal-border, -ib WIDTH width between text and main border\n\
--line-spacing, -lsp PIXELS additional space to put between lines\n\
--mouse-color, -ms COLOR mouse cursor color in Emacs window\n\
--name NAME title of main Emacs window\n\
--reverse-video, -r, -rv switch foreground and background\n\
--title, -T, -wn, TITLE title for Emacs windows\n\
--vertical-scroll-bars, -vb enable vertical scroll bars\n\
--xrm XRESOURCES set additional X resources\n\
\n\
You can generally also specify long option names with a single -; for\n\
example, -batch as well as --batch. You can use any unambiguous\n\
abbreviation for a --option.\n\
\n\
Various environment variables and window system resources also affect\n\
Emacs' operation. See the main documentation.\n\
\n\
Report bugs to bug-gnu-emacs@gnu.org. First, please see the Bugs\n\
section of the Emacs manual or the file BUGS.\n"
int fatal_error_code;
int fatal_error_in_progress;
#ifdef SIGUSR1
SIGTYPE
handle_USR1_signal (sig)
int sig;
{
struct input_event buf;
bzero (&buf, sizeof buf);
buf.kind = USER_SIGNAL_EVENT;
buf.frame_or_window = selected_frame;
kbd_buffer_store_event (&buf);
}
#endif
#ifdef SIGUSR2
SIGTYPE
handle_USR2_signal (sig)
int sig;
{
struct input_event buf;
bzero (&buf, sizeof buf);
buf.kind = USER_SIGNAL_EVENT;
buf.code = 1;
buf.frame_or_window = selected_frame;
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
#if ! defined (DOS_NT) && ! defined (NO_ABORT)
#ifndef ABORT_RETURN_TYPE
#define ABORT_RETURN_TYPE void
#endif
ABORT_RETURN_TYPE
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 = NULL;
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 ()
{
#ifndef USE_CRT_DLL
extern char **environ;
#endif
if (initialized)
{
if (!malloc_using_checking)
{
char **p;
for (p = environ; p && *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;
{
#if GC_MARK_STACK
Lisp_Object dummy;
#endif
char stack_bottom_variable;
int do_initial_setlocale;
int skip_args = 0;
#ifndef USE_CRT_DLL
extern int errno;
#endif
#ifdef HAVE_SETRLIMIT
struct rlimit rlim;
#endif
int no_loadup = 0;
#if GC_MARK_STACK
extern Lisp_Object *stack_base;
stack_base = &dummy;
#endif
#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) 2001 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)
{
fprintf (stderr, "Fatal malloc_jumpstart() error\n");
exit (1);
}
}
}
#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
{
char *lc_all = getenv ("LC_ALL");
do_initial_setlocale = ! lc_all || strcmp (lc_all, "C");
}
if (do_initial_setlocale)
setlocale (LC_ALL, "");
#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;
emacs_close (0);
emacs_close (1);
result = emacs_open (term, O_RDWR, 0);
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 (USAGE1, argv[0]);
printf (USAGE2);
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
}
init_signals ();
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 ();
syms_of_xfaces ();
syms_of_keyboard ();
#ifdef macintosh
syms_of_textprop ();
syms_of_macfns ();
syms_of_ccl ();
syms_of_fontset ();
syms_of_macterm ();
syms_of_macmenu ();
syms_of_data ();
syms_of_search ();
syms_of_frame ();
x_term_init ();
init_keyboard ();
#endif
init_window_once ();
init_fileio_once ();
}
init_alloc ();
if (do_initial_setlocale)
{
fixup_locale ();
Vsystem_messages_locale = Vprevious_system_messages_locale;
Vsystem_time_locale = Vprevious_system_time_locale;
}
init_eval ();
init_data ();
#ifdef CLASH_DETECTION
init_filelock ();;
#endif
init_atimer ();
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 = XCDR (tail))
{
Lisp_Object buffer;
buffer = Fcdr (XCAR (tail));
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 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)
{
#ifndef macintosh
syms_of_data ();
#endif
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 ();
#ifndef macintosh
syms_of_ccl ();
#endif
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_keymap ();
syms_of_macros ();
syms_of_marker ();
syms_of_minibuf ();
syms_of_mocklisp ();
syms_of_process ();
#ifndef macintosh
syms_of_search ();
syms_of_frame ();
#endif
syms_of_syntax ();
syms_of_term ();
syms_of_undo ();
#ifdef HAVE_SOUND
syms_of_sound ();
#endif
#ifndef macintosh
syms_of_textprop ();
#endif
syms_of_composite ();
#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
#ifndef macintosh
syms_of_xmenu ();
#endif
#endif
#ifdef HAVE_NTGUI
syms_of_w32term ();
syms_of_w32fns ();
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 ();
}
#ifndef macintosh
init_keyboard ();
#endif
#ifdef VMS
init_vmsproc ();
#endif
init_sys_modes ();
#ifdef HAVE_X_WINDOWS
init_xfns ();
#endif
init_fns ();
init_xdisp ();
init_macros ();
init_editfns ();
init_floatfns ();
#ifdef VMS
init_vmsfns ();
#endif
init_emacs_process ();
#ifdef HAVE_SOUND
init_sound ();
#endif
init_window ();
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
}
#if defined (__FreeBSD__) || defined (__linux)
#ifdef PROFILING
if (initialized)
{
extern void _mcleanup ();
extern char etext;
extern void safe_bcopy ();
extern void dump_opcode_frequencies ();
atexit (_mcleanup);
monstartup (safe_bcopy, &etext);
}
else
moncontrol (0);
#endif
#endif
initialized = 1;
#ifdef LOCALTIME_CACHE
tzset ();
#endif
Frecursive_edit ();
return 0;
}
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 },
{ "-execute", "--execute", 0, 1 },
{ "-find-file", "--find-file", 0, 1 },
{ "-visit", "--visit", 0, 1 },
{ "-file", "--file", 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;
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;
{
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
if (sig == 0 || sig == SIGTERM)
{
check_glyph_memory ();
check_message_stack ();
}
#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
#ifdef USE_MMAP_FOR_BUFFERS
mmap_set_vars (0);
#endif
unexec (XSTRING (filename)->data,
!NILP (symfile) ? XSTRING (symfile)->data : 0, my_edata, 0, 0);
#ifdef USE_MMAP_FOR_BUFFERS
mmap_set_vars (1);
#endif
#ifdef DOUG_LEA_MALLOC
free (malloc_state_ptr);
#endif
#endif
Vpurify_flag = tem;
return unbind_to (count, Qnil);
}
#endif
#endif
#if HAVE_SETLOCALE
void
fixup_locale ()
{
setlocale (LC_NUMERIC, "C");
}
static void
synchronize_locale (category, plocale, desired_locale)
int category;
Lisp_Object *plocale;
Lisp_Object desired_locale;
{
if (! EQ (*plocale, desired_locale))
{
*plocale = desired_locale;
setlocale (category, (STRINGP (desired_locale)
? (char *)(XSTRING (desired_locale)->data)
: ""));
}
}
void
synchronize_system_time_locale ()
{
synchronize_locale (LC_TIME, &Vprevious_system_time_locale,
Vsystem_time_locale);
}
void
synchronize_system_messages_locale ()
{
#ifdef LC_MESSAGES
synchronize_locale (LC_MESSAGES, &Vprevious_system_messages_locale,
Vsystem_messages_locale);
#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.\n\
On MS-Windows, the value reflects the OS flavor and version on which\n\
Emacs is running.");
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;
DEFVAR_LISP ("system-messages-locale", &Vsystem_messages_locale,
"System locale for messages.");
Vsystem_messages_locale = Qnil;
DEFVAR_LISP ("previous-system-messages-locale",
&Vprevious_system_messages_locale,
"Most recently used system locale for messages.");
Vprevious_system_messages_locale = Qnil;
DEFVAR_LISP ("system-time-locale", &Vsystem_time_locale,
"System locale for time.");
Vsystem_time_locale = Qnil;
DEFVAR_LISP ("previous-system-time-locale", &Vprevious_system_time_locale,
"Most recently used system locale for time.");
Vprevious_system_time_locale = Qnil;
}