X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/ea2acec55b169b4978569fcdbd4c0b70256df313..cc94f3b24e447e04da3e899af8909cb77d648ef0:/src/emacs.c?ds=sidebyside diff --git a/src/emacs.c b/src/emacs.c index bf701f8666..0dc6e07fb3 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1,5 +1,5 @@ /* Fully extensible Emacs, running on Unix, intended for GNU. - Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc. + Copyright (C) 1985,86,87,93,94,95,97,98,1999 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -19,10 +19,9 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include - -#include #include #include @@ -32,6 +31,10 @@ Boston, MA 02111-1307, USA. */ #include #endif +#ifdef HAVE_UNISTD_H +#include +#endif + #ifdef BSD_SYSTEM #include #endif @@ -39,11 +42,18 @@ Boston, MA 02111-1307, USA. */ #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 +#endif #ifdef HAVE_SETRLIMIT #include @@ -57,7 +67,18 @@ Boston, MA 02111-1307, USA. */ extern void malloc_warning (); extern void set_time_zone_rule (); extern char *index (); -extern char *strerror (); + +/* Make these values available in GDB, which doesn't see macros. */ + +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; /* Command line args from shell, as list of strings */ Lisp_Object Vcommand_line_args; @@ -76,6 +97,17 @@ Lisp_Object Vinstallation_directory; /* Hook run by `kill-emacs' before it does really anything. */ Lisp_Object Vkill_emacs_hook; +#ifdef SIGUSR1 +/* Hooks for signal USR1 and USR2 handing */ +Lisp_Object Vsignal_USR1_hook; +#ifdef SIGUSR2 +Lisp_Object Vsignal_USR2_hook; +#endif +#endif + +/* Search path separator. */ +Lisp_Object Vpath_separator; + /* Set nonzero after Emacs has started up the first time. Prevents reinitialization of the Lisp world and keymaps on subsequent starts. */ @@ -89,6 +121,9 @@ void *malloc_state_ptr; extern void *malloc_get_state (); /* From glibc, a routine that overwrites the malloc internal state. */ extern void malloc_set_state (); +/* Non-zero if the MALLOC_CHECK_ enviroment variable was set while + dumping. Used to work around a bug in glibc's malloc. */ +int malloc_using_checking; #endif /* Variable whose value is symbol giving operating system type. */ @@ -103,6 +138,12 @@ Lisp_Object Vsystem_configuration_options; Lisp_Object Qfile_name_handler_alist; +/* Current and previous system locales for messages and time. */ +Lisp_Object Vsystem_messages_locale; +Lisp_Object Vprevious_system_messages_locale; +Lisp_Object Vsystem_time_locale; +Lisp_Object Vprevious_system_time_locale; + /* 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; @@ -158,6 +199,79 @@ 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\ ++LINENUM FILE visit FILE using find-file, then go to line LINENUM\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\ +--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" + /* Signal code for the fatal signal that was received */ int fatal_error_code; @@ -165,6 +279,40 @@ int fatal_error_code; /* Nonzero if handling a fatal error already */ 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 = selected_frame; + buf.modifiers = 0; + buf.timestamp = 0; + + kbd_buffer_store_event (&buf); +} +#endif /* SIGUSR1 */ + +#ifdef SIGUSR2 +SIGTYPE +handle_USR2_signal (sig) + int sig; +{ + struct input_event buf; + + buf.kind = user_signal; + buf.code = 1; + buf.frame_or_window = selected_frame; + buf.modifiers = 0; + buf.timestamp = 0; + + kbd_buffer_store_event (&buf); +} +#endif /* SIGUSR2 */ + /* Handle bus errors, illegal instruction, etc. */ SIGTYPE fatal_error_signal (sig) @@ -212,10 +360,30 @@ memory_warning_signal (sig) force_auto_save_soon (); } #endif + +/* We define abort, rather than using it from the library, + so that GDB can return from a breakpoint here. + MSDOS has its own definition on msdos.c */ + +#if ! defined (DOS_NT) && ! defined (NO_ABORT) + +#ifndef ABORT_RETURN_TYPE +#define ABORT_RETURN_TYPE void +#endif + +ABORT_RETURN_TYPE +abort () +{ + kill (getpid (), SIGABRT); + /* This shouldn't be executed, but it prevents a warning. */ + exit (1); +} +#endif + /* Code for dealing with Lisp access to the Unix command line */ -static +static void init_cmdargs (argc, argv, skip_args) int argc; char **argv; @@ -392,11 +560,11 @@ static char dump_tz[] = "UtC0"; (We don't have any real constructors or destructors.) */ #ifdef __GNUC__ #ifndef GCC_CTORS_IN_LIBC -__do_global_ctors () +void __do_global_ctors () {} -__do_global_ctors_aux () +void __do_global_ctors_aux () {} -__do_global_dtors () +void __do_global_dtors () {} /* Linux has a bug in its library; avoid an error. */ #ifndef LINUX @@ -404,7 +572,7 @@ char * __CTOR_LIST__[2] = { (char *) (-1), 0 }; #endif char * __DTOR_LIST__[2] = { (char *) (-1), 0 }; #endif /* GCC_CTORS_IN_LIBC */ -__main () +void __main () {} #endif /* __GNUC__ */ #endif /* ORDINARY_LINK */ @@ -478,36 +646,81 @@ argmatch (argv, argc, sstr, lstr, minlen, valptr, skipptr) } } +#ifdef DOUG_LEA_MALLOC + +/* malloc can be invoked even before main (e.g. by the dynamic + linker), so the dumped malloc state must be restored as early as + possible using this special hook. */ + +static void +malloc_initialize_hook () +{ + extern char **environ; + + if (initialized) + { + if (!malloc_using_checking) + /* Work around a bug in glibc's malloc. MALLOC_CHECK_ must be + ignored if the heap to be restored was constructed without + malloc checking. Can't use unsetenv, since that calls malloc. */ + { + 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 /* DOUG_LEA_MALLOC */ + /* ARGSUSED */ +int main (argc, argv, envp) int argc; char **argv; char **envp; { char stack_bottom_variable; + int do_initial_setlocale; int skip_args = 0; extern int errno; - extern sys_nerr; + extern int sys_nerr; #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif + int no_loadup = 0; #ifdef LINUX_SBRK_BUG __sbrk (1); #endif -#ifdef DOUG_LEA_MALLOC +#ifdef RUN_TIME_REMAP if (initialized) - { - malloc_set_state (malloc_state_ptr); - free (malloc_state_ptr); - r_alloc_reinit (); - } + 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)) + if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args) + /* We don't know the version number unless this is a dumped Emacs. + So ignore --version otherwise. */ + && initialized) { Lisp_Object tem; tem = Fsymbol_value (intern ("emacs-version")); @@ -519,12 +732,12 @@ main (argc, argv, envp) else { printf ("GNU Emacs %s\n", XSTRING (tem)->data); - printf ("Copyright (C) 1996 Free Software Foundation, Inc.\n"); + 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 files named COPYING.\n"); + printf ("see the file named COPYING.\n"); exit (0); } } @@ -579,12 +792,25 @@ main (argc, argv, envp) #endif /* VMS */ #if defined (HAVE_SETRLIMIT) && defined (RLIMIT_STACK) - /* Extend the stack space available. */ - if (!getrlimit (RLIMIT_STACK, &rlim)) + /* Extend the stack space available. + Don't do that if dumping, since some systems (e.g. DJGPP) + might define a smaller stack limit at that time. */ + if (1 +#ifndef CANNOT_DUMP + && (!noninteractive || initialized) +#endif + && !getrlimit (RLIMIT_STACK, &rlim)) { long newlim; - /* Approximate the amount regex.c needs, plus some more. */ - newlim = 800000 * sizeof (char *); + extern int re_max_failures; + /* Approximate the amount regex.c needs per unit of re_max_failures. */ + int ratio = 20 * sizeof (char *); + /* Then add 33% to cover the size of the smaller stacks that regex.c + successively allocates and discards, on its way to the maximum. */ + ratio += ratio / 3; + /* Add in some extra to cover + what we're likely to use for other reasons. */ + newlim = re_max_failures * ratio + 200000; #ifdef __NetBSD__ /* NetBSD (at least NetBSD 1.2G and former) has a bug in its stack allocation routine for new process that the allocation @@ -593,7 +819,11 @@ main (argc, argv, envp) newlim = (newlim + getpagesize () - 1) / getpagesize () * getpagesize(); #endif if (newlim > rlim.rlim_max) - newlim = rlim.rlim_max; + { + newlim = rlim.rlim_max; + /* Don't let regex.c overflow the stack we have. */ + re_max_failures = (newlim - 200000) / ratio; + } if (rlim.rlim_cur < newlim) rlim.rlim_cur = newlim; @@ -604,11 +834,6 @@ main (argc, argv, envp) /* Record (approximately) where the stack begins. */ stack_bottom = &stack_bottom_variable; -#ifdef RUN_TIME_REMAP - if (initialized) - run_time_remap (argv[0]); -#endif - #ifdef USG_SHARED_LIBRARIES if (bss_end) brk ((void *)bss_end); @@ -617,15 +842,15 @@ main (argc, argv, envp) clearerr (stdin); #ifndef SYSTEM_MALLOC - if (! initialized) - { - /* Arrange to get warning messages as memory fills up. */ - memory_warnings (0, malloc_warning); + /* Arrange to get warning messages as memory fills up. */ + memory_warnings (0, malloc_warning); - /* Arrange to disable interrupt input while malloc and friends are - running. */ - uninterrupt_malloc (); - } + /* Call malloc at least once, to run the initial __malloc_hook. + Also call realloc and free for consistency. */ + free (realloc (malloc (4), 4)); + + /* Arrange to disable interrupt input inside malloc etc. */ + uninterrupt_malloc (); #endif /* not SYSTEM_MALLOC */ #ifdef MSDOS @@ -654,6 +879,20 @@ main (argc, argv, envp) setuid (getuid ()); #endif /* SET_EMACS_PRIORITY */ + /* Skip initial setlocale if LC_ALL is "C", as it's not needed in that case. + The build procedure uses this while dumping, to ensure that the + dumped Emacs does not have its system locale tables initialized, + as that might cause screwups when the dumped Emacs starts up. */ + { + char *lc_all = getenv ("LC_ALL"); + do_initial_setlocale = ! lc_all || strcmp (lc_all, "C"); + } + + /* Set locale now, so that initial error messages are localized properly. + fixup_locale must wait until later, since it builds strings. */ + if (do_initial_setlocale) + setlocale (LC_ALL, ""); + #ifdef EXTRA_INITIALIZE EXTRA_INITIALIZE; #endif @@ -661,32 +900,36 @@ main (argc, argv, envp) inhibit_window_system = 0; /* Handle the -t switch, which specifies filename to use as terminal */ - { - 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); + 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; /* -t => -nw */ + inhibit_window_system = 1; /* -t => -nw */ #endif - } - } + } + else + break; + } + if (argmatch (argv, argc, "-nw", "--no-windows", 6, NULL, &skip_args)) inhibit_window_system = 1; @@ -698,59 +941,11 @@ main (argc, argv, envp) /* Handle the --help option, which gives a usage message.. */ if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args)) { - 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\ -Report bugs to bug-gnu-emacs@prep.ai.mit.edu. First, please see\n\ -the Bugs section of the Emacs manual or the file BUGS.", argv[0]); + printf (USAGE1, argv[0]); + printf (USAGE2); exit (0); } -#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 = 0; - 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 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) { #ifdef BSD_PGRPS @@ -766,9 +961,7 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); #endif } -#ifdef POSIX_SIGNALS init_signals (); -#endif /* Don't catch SIGHUP if dumping. */ if (1 @@ -800,6 +993,12 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); 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 @@ -879,15 +1078,159 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); init_casetab_once (); init_buffer_once (); /* Create buffer table and some buffers */ init_minibuf_once (); /* Create list of minibuffers */ - /* Must precede init_window_once */ + /* Must precede init_window_once */ + + /* Call syms_of_xfaces before init_window_once because that + function creates Vterminal_frame. Termcap frames now use + faces, and the face implementation uses some symbols as + face names. */ +#ifndef HAVE_NTGUI + syms_of_xfaces (); +#endif + init_window_once (); /* Init the window system */ + init_fileio_once (); /* Must precede any path manipulation. */ } 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_coding (); init_data (); +#ifdef CLASH_DETECTION + init_filelock ();; +#endif + init_atimer (); running_asynch_code = 0; + /* Handle --unibyte and the EMACS_UNIBYTE envvar, + but not while dumping. */ + if ( +#ifndef CANNOT_DUMP + ! noninteractive || initialized +#else + 1 +#endif + ) + { + int inhibit_unibyte = 0; + + /* --multibyte overrides EMACS_UNIBYTE. */ + if (argmatch (argv, argc, "-no-unibyte", "--no-unibyte", 4, NULL, &skip_args) + || argmatch (argv, argc, "-multibyte", "--multibyte", 4, NULL, &skip_args)) + inhibit_unibyte = 1; + + /* --unibyte requests that we set up to do everything with single-byte + buffers and strings. We need to handle this before calling + init_lread, init_editfns and other places that generate Lisp strings + from text in the environment. */ + /* Actually this shouldn't be needed as of 20.4 in a generally + unibyte environment. As handa says, environment values + aren't now decoded; also existing buffers are now made + unibyte during startup if .emacs sets unibyte. Tested with + 8-bit data in environment variables and /etc/passwd, setting + unibyte and Latin-1 in .emacs. -- Dave Love */ + 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) + { + /* Erase pre-dump messages in *Messages* now so no abort. */ + 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)); + /* Verify that all buffers are empty now, as they + ought to be. */ + if (BUF_Z (XBUFFER (buffer)) > BUF_BEG (XBUFFER (buffer))) + abort (); + /* It is safe to do this crudely in an empty buffer. */ + XBUFFER (buffer)->enable_multibyte_characters = Qnil; + } + } + } + + no_loadup + = !argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args); + + +#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 = 0; + int count_before = skip_args; + + /* Skip any number of -d options, but only use the last one. */ + 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 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 count_before + && argv[count_before + 1][1] == '-') + argv[count_before + 1] = "-d"; + + /* Don't actually discard this arg. */ + skip_args = count_before; + } +#endif + + /* argmatch must not be used after here, + except when bulding temacs + because the -d argument has not been skipped in skip_args. */ + #ifdef MSDOS /* Call early 'cause init_environment needs it. */ init_dosfns (); @@ -900,7 +1243,7 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); #ifdef WINDOWSNT /* Initialize environment from registry settings. */ - init_environment (); + init_environment (argv); init_ntproc (); /* must precede init_editfns */ #endif @@ -911,7 +1254,8 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); /* AIX crashes are reported in system versions 3.2.3 and 3.2.4 if this is not done. Do it after set_process_environment so that we don't pollute Vprocess_environment. */ -#ifdef AIX + /* Setting LANG here will defeat the startup locale processing... */ +#ifdef AIX3_2 putenv ("LANG=C"); #endif @@ -926,40 +1270,15 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); Lisp_Object old_log_max; old_log_max = Vmessage_log_max; XSETFASTINT (Vmessage_log_max, 0); - message_dolog ("", 0, 1); + message_dolog ("", 0, 1, 0); Vmessage_log_max = old_log_max; } init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ init_lread (); - if (!noninteractive) - { -#ifdef VMS - init_vms_input ();/* init_display calls get_frame_size, that needs this */ -#endif /* VMS */ - init_display (); /* Determine terminal type. init_sys_modes uses results */ - } - init_keyboard (); /* This too must precede init_sys_modes */ -#ifdef VMS - init_vmsproc (); /* And this too. */ -#endif /* VMS */ - init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.) */ - init_xdisp (); - init_macros (); - init_editfns (); -#ifdef LISP_FLOAT_TYPE - init_floatfns (); -#endif -#ifdef VMS - init_vmsfns (); -#endif /* VMS */ - init_process (); -#ifdef CLASH_DETECTION - init_filelock (); -#endif /* CLASH_DETECTION */ - -/* Intern the names of all standard functions and variables; define standard keys */ + /* Intern the names of all standard functions and variables; + define standard keys. */ if (!initialized) { @@ -1011,9 +1330,12 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); syms_of_syntax (); syms_of_term (); syms_of_undo (); +#ifdef HAVE_SOUND + syms_of_sound (); +#endif - /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */ syms_of_textprop (); + syms_of_composite (); #ifdef VMS syms_of_vmsproc (); #endif /* VMS */ @@ -1032,7 +1354,6 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); #endif /* HAVE_X_WINDOWS */ #ifndef HAVE_NTGUI - syms_of_xfaces (); syms_of_xmenu (); #endif @@ -1042,6 +1363,7 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); syms_of_w32faces (); syms_of_w32select (); syms_of_w32menu (); + syms_of_fontset (); #endif /* HAVE_NTGUI */ #ifdef SYMS_SYSTEM @@ -1063,16 +1385,44 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); keys_of_frame (); } + if (!noninteractive) + { +#ifdef VMS + init_vms_input ();/* init_display calls get_frame_size, that needs this */ +#endif /* VMS */ + init_display (); /* Determine terminal type. init_sys_modes uses results */ + } + init_keyboard (); /* This too must precede init_sys_modes */ +#ifdef VMS + init_vmsproc (); /* And this too. */ +#endif /* VMS */ + init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.) */ +#ifdef HAVE_X_WINDOWS + init_xfns (); +#endif /* HAVE_X_WINDOWS */ + init_fns (); + init_xdisp (); + init_macros (); + init_editfns (); + init_floatfns (); +#ifdef VMS + init_vmsfns (); +#endif /* VMS */ + init_process (); +#ifdef HAVE_SOUND + init_sound (); +#endif + if (!initialized) { char *file; - /* Handle -l loadup-and-dump, args passed by Makefile. */ + /* Handle -l loadup, args passed by Makefile. */ if (argmatch (argv, argc, "-l", "--load", 3, &file, &skip_args)) Vtop_level = Fcons (intern ("load"), Fcons (build_string (file), Qnil)); #ifdef CANNOT_DUMP /* Unless next switch is -nl, load "loadup.el" first thing. */ - if (!argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args)) + if (! no_loadup) Vtop_level = Fcons (intern ("load"), Fcons (build_string ("loadup.el"), Qnil)); #endif /* CANNOT_DUMP */ @@ -1098,6 +1448,31 @@ the Bugs section of the Emacs manual or the file BUGS.", argv[0]); #endif } + /* Gerd Moellmann says this makes profiling work on + FreeBSD. It might work on some other systems too. + Give it a try and tell me if it works on your system. */ +#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); + // atexit (dump_opcode_frequencies); + /* This uses safe_bcopy because that function comes first in the + Emacs executable. It might be better to use something that + gives the start of the text segment, but start_of_text is not + defined on all systems now. */ + monstartup (safe_bcopy, &etext); + } + else + moncontrol (0); +#endif +#endif + initialized = 1; #ifdef LOCALTIME_CACHE @@ -1129,17 +1504,28 @@ struct standard_args struct standard_args standard_args[] = { - { "-version", "--version", 110, 0 }, - { "-help", "--help", 110, 0 }, - { "-nl", "--no-shared-memory", 100, 0 }, + { "-version", "--version", 150, 0 }, +#ifdef HAVE_SHM + { "-nl", "--no-shared-memory", 140, 0 }, +#endif #ifdef VMS - { "-map", "--map-data", 100, 0 }, + { "-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 - { "-t", "--terminal", 90, 1 }, - { "-d", "--display", 80, 1 }, - { "-display", 0, 80, 1 }, - { "-nw", "--no-windows", 70, 0 }, - { "-batch", "--batch", 60, 0 }, + /* -d must come last before the options handled in startup.el. */ + { "-d", "--display", 60, 1 }, + { "-display", 0, 60, 1 }, + /* Now for the options handled in startup.el. */ { "-q", "--no-init-file", 50, 0 }, { "-no-init-file", 0, 50, 0 }, { "-no-site-file", "--no-site-file", 40, 0 }, @@ -1180,8 +1566,10 @@ struct standard_args standard_args[] = { "-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 }, /* This should be processed after ordinary file name args and the like. */ { "-kill", "--kill", -10, 0 }, @@ -1190,7 +1578,10 @@ struct standard_args standard_args[] = /* 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. */ + If an option takes an argument, keep it and its argument together. + + If an option that takes no argument appears more + than once, eliminate all but one copy of it. */ static void sort_args (argc, argv) @@ -1206,9 +1597,9 @@ sort_args (argc, argv) 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; /* Categorize all the options, and figure out which argv elts are option arguments. */ @@ -1223,7 +1614,7 @@ sort_args (argc, argv) /* If we have found "--", don't consider any more arguments as options. */ - if (argv[from][1] == '-') + if (argv[from][1] == '-' && argv[from][2] == 0) { /* Leave the "--", and everything following it, at the end. */ for (; from < argc; from++) @@ -1289,7 +1680,7 @@ sort_args (argc, argv) /* Copy the arguments, in order of decreasing priority, to NEW. */ new[0] = argv[0]; - while (to < argc) + while (incoming_used < argc) { int best = -1; int best_priority = -9999; @@ -1311,10 +1702,17 @@ sort_args (argc, argv) 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]; + /* Copy the highest priority remaining option, with its args, to NEW. + Unless it is a duplicate of the previous one. */ + 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); /* Clear out this option in ARGV. */ argv[best] = 0; @@ -1322,6 +1720,10 @@ sort_args (argc, argv) argv[best + i + 1] = 0; } + /* If duplicate options were deleted, fill up extra space with null ptrs. */ + while (to < argc) + new[to++] = 0; + bcopy (new, argv, sizeof (char *) * argc); free (options); @@ -1339,8 +1741,6 @@ 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); @@ -1451,6 +1851,13 @@ shut_down_emacs (sig, no_x, stuff) #ifdef WINDOWSNT term_ntproc (); #endif + + check_glyph_memory (); + check_message_stack (); + +#ifdef MSDOS + dos_cleanup (); +#endif } @@ -1564,6 +1971,53 @@ You must run Emacs in batch mode in order to dump it.") #endif /* not CANNOT_DUMP */ +#if HAVE_SETLOCALE +/* Recover from setlocale (LC_ALL, ""). */ +void +fixup_locale () +{ + /* The Emacs Lisp reader needs LC_NUMERIC to be "C", + so that numbers are read and printed properly for Emacs Lisp. */ + setlocale (LC_NUMERIC, "C"); +} + +/* Set system locale CATEGORY, with previous locale *PLOCALE, to + DESIRED_LOCALE. */ +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) + : "")); + } +} + +/* Set system time locale to match Vsystem_time_locale, if possible. */ +void +synchronize_system_time_locale () +{ + synchronize_locale (LC_TIME, &Vprevious_system_time_locale, + Vsystem_time_locale); +} + +/* Set system messages locale to match Vsystem_messages_locale, if + possible. */ +void +synchronize_system_messages_locale () +{ +#ifdef LC_MESSAGES + synchronize_locale (LC_MESSAGES, &Vprevious_system_messages_locale, + Vsystem_messages_locale); +#endif +} +#endif /* HAVE_SETLOCALE */ + #ifndef SEPCHAR #define SEPCHAR ':' #endif @@ -1621,6 +2075,7 @@ decode_env_path (evarname, defalt) return Fnreverse (lpath); } +void syms_of_emacs () { Qfile_name_handler_alist = intern ("file-name-handler-alist"); @@ -1665,6 +2120,18 @@ 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\ @@ -1674,6 +2141,13 @@ 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."); @@ -1688,4 +2162,21 @@ 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; }