SXEmacs, meet Dbus. Dbus, meet SXEmacs
[sxemacs] / src / emacs.c
1 /* SXEmacs -- Fully extensible Emacs, running on Unix and other platforms.
2    Copyright (C) 1985, 1986, 1987, 1992, 1993, 1994
3    Free Software Foundation, Inc.
4    Copyright (C) 1995 Sun Microsystems, Inc.
5    Copyright (C) 2000, 2002 Ben Wing.
6    Copyright (C) 2004 Steve Youngs.
7
8 This file is part of SXEmacs
9
10 SXEmacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 SXEmacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
22
23
24 /* Synched up with: Mule 2.0, FSF 19.28. */
25
26 /* Capsule summary of the various releases of Lucid Emacs/SXEmacs and
27    FSF/GNU Emacs.  Provided here for use in cross-referencing version
28    releases and dates in comments, esp. in the authorship comments at
29    the beginning of each file.  More information about history can be
30    found in the beginning of the Internals Manual and in the About page.
31
32 -- A time line for Lucid Emacs/XEmacs is
33
34 version 19.0 shipped with Energize 1.0, April 1992.
35 version 19.1 released June 4, 1992.
36 version 19.2 released June 19, 1992.
37 version 19.3 released September 9, 1992.
38 version 19.4 released January 21, 1993.
39 version 19.5 was a repackaging of 19.4 with a few bug fixes and
40   shipped with Energize 2.0.  Never released to the net.
41 version 19.6 released April 9, 1993.
42 version 19.7 was a repackaging of 19.6 with a few bug fixes and
43   shipped with Energize 2.1.  Never released to the net.
44 version 19.8 released September 6, 1993.
45 version 19.9 released January 12, 1994.
46 version 19.10 released May 27, 1994.
47 version 19.11 (first XEmacs) released September 13, 1994.
48 version 19.12 released June 23, 1995.
49 version 19.13 released September 1, 1995.
50 version 19.14 released June 23, 1996.
51 version 20.0 released February 9, 1997.
52 version 19.15 released March 28, 1997.
53 version 20.1 (not released to the net) April 15, 1997.
54 version 20.2 released May 16, 1997.
55 version 19.16 released October 31, 1997.
56 version 20.3 (the first stable version of XEmacs 20.x) released
57   November 30, 1997.
58 version 20.4 released February 28, 1998.
59
60 -- A time line for GNU Emacs version 19 is
61
62 version 19.7 (beta) (first beta release) released May 22, 1993.
63 version 19.8 (beta) released May 27, 1993.
64 version 19.9 (beta) released May 27, 1993.
65 version 19.10 (beta) released May 30, 1993.
66 version 19.11 (beta) released June 1, 1993.
67 version 19.12 (beta) released June 2, 1993.
68 version 19.13 (beta) released June 8, 1993.
69 version 19.14 (beta) released June 17, 1993.
70 version 19.15 (beta) released June 19, 1993.
71 version 19.16 (beta) released July 6, 1993.
72 version 19.17 (beta) released late July, 1993.
73 version 19.18 (beta) released August 9, 1993.
74 version 19.19 (beta) released August 15, 1993.
75 version 19.20 (beta) released November 17, 1993.
76 version 19.21 (beta) released November 17, 1993.
77 version 19.22 (beta) released November 28, 1993.
78 version 19.23 (beta) released May 17, 1994.
79 version 19.24 (beta) released May 16, 1994.
80 version 19.25 (beta) released June 3, 1994.
81 version 19.26 (beta) released September 11, 1994.
82 version 19.27 (beta) released September 14, 1994.
83 version 19.28 (first ``official'' release) released November 1, 1994.
84 version 19.29 released June 21, 1995.
85 version 19.30 released November 24, 1995.
86 version 19.31 released May 25, 1996.
87 version 19.32 released July 31, 1996.
88 version 19.33 released August 11, 1996.
89 version 19.34 released August 21, 1996.
90 version 19.34b released September 6, 1996.
91
92 -- A time line for GNU Emacs version 20 is
93
94 version 20.1 released September 17, 1997.
95 version 20.2 released September 20, 1997.
96 version 20.3 released August 19, 1998.
97
98 -- A time line for GNU Emacs version 18 and older is
99
100 GNU Emacs version 13 (the first public release) was released on
101   March 20, 1985.
102 GNU Emacs version 15 (15.34) was released on May 7, 1985 and
103   shared some code with a version of Emacs written by James Gosling (the
104   same James Gosling who later created the Java language).
105 GNU Emacs version 16 (first released version was 16.56) was released on
106   July 15, 1985.  All Gosling code was removed due to potential copyright
107   problems with the code.
108 version 16.57: released on September 16, 1985.
109 versions 16.58, 16.59: released on September 17, 1985.
110 version 16.60: released on September 19, 1985.  These later version 16's
111   incorporated patches from the net, esp. for getting Emacs to work under
112   System V.
113 version 17.36 (first official v17 release) released on December 20, 1985.
114   Included a TeX-able user manual.  First official unpatched version that
115    worked on vanilla System V machines.
116 version 17.43 (second official v17 release) released on January 25, 1986.
117 version 17.45 released on January 30, 1986.
118 version 17.46 released on February 4, 1986.
119 version 17.48 released on February 10, 1986.
120 version 17.49 released on February 12, 1986.
121 version 17.55 released on March 18, 1986.
122 version 17.57 released on March 27, 1986.
123 version 17.58 released on April 4, 1986.
124 version 17.61 released on April 12, 1986.
125 version 17.63 released on May 7, 1986.
126 version 17.64 released on May 12, 1986.
127 version 18.24 (a beta version) released on October 2, 1986.
128 version 18.30 (a beta version) released on November 15, 1986.
129 version 18.31 (a beta version) released on November 23, 1986.
130 version 18.32 (a beta version) released on December 7, 1986.
131 version 18.33 (a beta version) released on December 12, 1986.
132 version 18.35 (a beta version) released on January 5, 1987.
133 version 18.36 (a beta version) released on January 21, 1987.
134 January 27, 1987: The Great Usenet Renaming.  net.emacs is now comp.emacs.
135 version 18.37 (a beta version) released on February 12, 1987.
136 version 18.38 (a beta version) released on March 3, 1987.
137 version 18.39 (a beta version) released on March 14, 1987.
138 version 18.40 (a beta version) released on March 18, 1987.
139 version 18.41 (the first ``official'' release) released on March 22, 1987.
140 version 18.45 released on June 2, 1987.
141 version 18.46 released on June 9, 1987.
142 version 18.47 released on June 18, 1987.
143 version 18.48 released on September 3, 1987.
144 version 18.49 released on September 18, 1987.
145 version 18.50 released on February 13, 1988.
146 version 18.51 released on May 7, 1988.
147 version 18.52 released on September 1, 1988.
148 version 18.53 released on February 24, 1989.
149 version 18.54 released on April 26, 1989.
150 version 18.55 released on August 23, 1989.  This is the earliest version
151   that is still available by FTP.
152 version 18.56 released on January 17, 1991.
153 version 18.57 released late January, 1991.
154 version 18.58 released ?????.
155 version 18.59 released October 31, 1992.
156
157 */
158
159 /* Note: It is necessary to specify <config.h> and not "config.h" in
160    order for the --srcdir type of compilation to work properly.
161    Otherwise the config.h from the srcdir, rather than the one from
162    the build dir, will be used. */
163
164 #include <config.h>
165 #include "lisp.h"
166
167 #include "backtrace.h"          /* run-emacs-from-temacs needs this */
168 #include "buffer.h"
169 #include "commands.h"
170 #include "ui/console.h"
171 #include "process.h"
172 #include "ui/redisplay.h"
173 #include "ui/frame.h"
174 #include "sysdep.h"
175
176 #include "syssignal.h"          /* Always include before systty.h */
177 #include "ui/TTY/systty.h"
178 #include "sysfile.h"
179 #include "systime.h"
180
181 #if defined WITH_EMODULES && defined HAVE_EMODULES
182 # include "emodules-ng.h"
183 #endif
184
185 #ifdef PDUMP
186 #include "dumper.h"
187 #endif
188
189 #ifndef SEPCHAR
190 #define SEPCHAR ':'
191 #endif
192
193 #ifdef QUANTIFY
194 #include <quantify.h>
195 #endif
196
197 #if defined WITH_EMODULES && defined HAVE_EMODULES && 0
198 #include "sysdll.h"
199 #endif
200
201 #if defined (HAVE_LOCALE_H) && \
202    (defined (I18N2) || defined (I18N3) || defined (I18N4))
203 #include <locale.h>
204 #endif
205
206 /* For PATH_EXEC */
207 #include <sxe-paths.h>
208
209 /* for stack exploitation */
210 #if defined HAVE_SYS_RESOURCE_H
211 # include <sys/resource.h>
212 #endif
213
214 /* for the reinit funs */
215 #include "skiplist.h"
216 #include "dllist.h"
217 #include "elhash.h"
218
219 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
220 # if defined HAVE_GC_GC_H
221 #  include "gc/gc.h"
222 # elif defined HAVE_GC_H
223 #  include "gc.h"
224 # elif 1
225 /* declare the 3 funs we need */
226 extern void *GC_init(void);
227 # else
228 #  error Go back to your planet!
229 # endif
230 #endif  /* HAVE_BDWGC */
231
232 #if !defined (SYSTEM_MALLOC) && !defined (DOUG_LEA_MALLOC)
233 extern void *(*__malloc_hook) (size_t);
234 extern void *(*__realloc_hook) (void *, size_t);
235 extern void (*__free_hook) (void *);
236 #endif                          /* not SYSTEM_MALLOC && not DOUG_LEA_MALLOC */
237
238 /* Command line args from shell, as list of strings */
239 Lisp_Object Vcommand_line_args;
240
241 /* Set nonzero after SXEmacs has started up the first time.
242   Prevents reinitialization of the Lisp world and keymaps
243   on subsequent starts.  */
244 int initialized;
245
246 #ifdef DOUG_LEA_MALLOC
247 # include <malloc.h>
248 /* Preserves a pointer to the memory allocated that copies that
249    static data inside glibc's malloc.  */
250 static void *malloc_state_ptr;
251 #endif                          /* DOUG_LEA_MALLOC */
252
253 # ifdef REL_ALLOC
254 void r_alloc_reinit(void);
255 # endif
256
257 /* Variable whose value is symbol giving operating system type. */
258 Lisp_Object Vsystem_type;
259
260 /* Variable whose value is string giving configuration built for.  */
261 Lisp_Object Vsystem_configuration;
262
263 /* Variable whose value is string containing the configuration options
264    SXEmacs was built with.  */
265 Lisp_Object Vsystem_configuration_options;
266
267 /* Version numbers and strings */
268 Lisp_Object Vemacs_major_version;
269 Lisp_Object Vemacs_minor_version;
270 Lisp_Object Vemacs_patch_level;
271 Lisp_Object Vemacs_beta_version;
272 Lisp_Object Vsxemacs_git_version;
273 Lisp_Object Vsxemacs_codename;
274 #ifdef INFODOCK
275 Lisp_Object Vinfodock_major_version;
276 Lisp_Object Vinfodock_minor_version;
277 Lisp_Object Vinfodock_build_version;
278 #endif
279
280 /* The path under which SXEmacs was invoked. */
281 Lisp_Object Vinvocation_path;
282
283 /* The name under which SXEmacs was invoked, with any leading directory
284    names discarded.  */
285 Lisp_Object Vinvocation_name;
286
287 /* The directory name from which SXEmacs was invoked.  */
288 Lisp_Object Vinvocation_directory;
289
290 #if 0                           /* FSFmacs */
291 /* The directory name in which to find subdirs such as lisp and etc.
292    nil means get them only from PATH_LOADSEARCH.  */
293 Lisp_Object Vinstallation_directory;
294 #endif
295
296 Lisp_Object Vemacs_program_name, Vemacs_program_version;
297 Lisp_Object Vexec_path;
298 Lisp_Object Vexec_directory, Vconfigure_exec_directory;
299 Lisp_Object Vlisp_directory, Vconfigure_lisp_directory;
300 Lisp_Object Vmule_lisp_directory, Vconfigure_mule_lisp_directory;
301 Lisp_Object Vmodule_directory, Vconfigure_module_directory;
302 Lisp_Object Vsite_module_directory, Vconfigure_site_module_directory;
303 Lisp_Object Vconfigure_package_path;
304 Lisp_Object Vdata_directory, Vconfigure_data_directory;
305 Lisp_Object Vdoc_directory, Vconfigure_doc_directory;
306 Lisp_Object Vconfigure_lock_directory;
307 Lisp_Object Vdata_directory_list;
308 Lisp_Object Vconfigure_info_directory;
309 Lisp_Object Vconfigure_info_path;
310 Lisp_Object Vinternal_error_checking;
311 Lisp_Object Vmail_lock_methods, Vconfigure_mail_lock_method;
312 Lisp_Object Vpath_separator;
313
314 /* The default base directory SXEmacs is installed under. */
315 Lisp_Object Vconfigure_exec_prefix_directory, Vconfigure_prefix_directory;
316
317 /* If nonzero, set SXEmacs to run at this priority.  This is also used
318    in child_setup and sys_suspend to make sure subshells run at normal
319    priority. */
320 Fixnum emacs_priority;
321
322 /* Some FSF junk with running_asynch_code, to preserve the match
323    data.  Not necessary because we don't call process filters
324    asynchronously (i.e. from within QUIT). */
325 /* #### Delete this when merging the rest of my code */
326 int running_asynch_code;
327
328 /* If non-zero, a window-system was specified on the command line. */
329 int display_arg;
330
331 /* Type of display specified.  We cannot use a Lisp symbol here because
332    Lisp symbols may not initialized at the time that we set this
333    variable. */
334 const char *display_use;
335
336 /* If non-zero, then the early error handler will only print the error
337    message and exit. */
338 int suppress_early_error_handler_backtrace;
339
340 /* An address near the bottom of the stack.
341    Tells GC how to save a copy of the stack.  */
342 char *stack_bottom;
343 /* the stack size as imposed by the system */
344 size_t sys_stk_sz = 0;
345
346 #ifdef USG_SHARED_LIBRARIES
347 /* If nonzero, this is the place to put the end of the writable segment
348    at startup.  */
349
350 uintptr_t bss_end = 0;
351 #endif
352
353 /* Number of bytes of writable memory we can expect to be able to get */
354 #ifdef _RLIM_T_DECLARED
355 rlim_t lim_data;
356 #else
357 unsigned long lim_data;
358 #endif
359
360 /* WARNING!
361
362    Some LISP-visible command-line options are set by SXEmacs _before_ the
363    data is dumped in building a --pdump SXEmacs, but used _after_ it is
364    restored in normal operation.  Thus the dump-time values overwrite the
365    values SXEmacs is getting at runtime.  Such variables must be saved
366    before loading the dumpfile, and restored afterward.
367
368    Therefore these variables may not be initialized in vars_of_emacs().
369
370    The save/restore is done immediately before and after pdump_load() in
371    main_1().  See that function for the current list of protected variables.
372
373    Note that saving/restoring is only necessary for a few variables that are
374      o command line arguments effective at runtime (as opposed to dump-time),
375      o parsed before pdump_load, and
376      o exported to Lisp via a DEFVAR.
377 */
378
379 /* Nonzero means running SXEmacs without interactive terminal.  */
380
381 int noninteractive;
382
383 /* Value of Lisp variable `noninteractive'.
384    Normally same as C variable `noninteractive'
385    but nothing terrible happens if user sets this one.
386
387    Shadowed from the pdumper by `noninteractive'. */
388
389 int noninteractive1;
390
391 /* Nonzero means don't perform site-modules searches at startup */
392 int inhibit_site_modules;
393
394 /* Nonzero means don't respect early packages at startup */
395 int inhibit_early_packages;
396
397 /* Nonzero means we warn about early packages shadowing late packages at startup */
398 int warn_early_package_shadows;
399
400 /* Nonzero means don't load package autoloads at startup */
401 int inhibit_autoloads;
402
403 /* Nonzero means don't load the dump file (ignored if not PDUMP)  */
404 int nodumpfile;
405
406 /* Nonzero means we assume all ttys are 8 color ANSI terminals */
407 int assume_colorterm;
408
409 /* Nonzero means print debug information about path searching */
410 int debug_paths;
411
412 /* Save argv and argc.  */
413 static Extbyte **initial_argv;  /* #### currently unused */
414 static int initial_argc;        /* #### currently unused */
415
416 static void sort_args(int argc, char **argv);
417
418 Lisp_Object Qkill_emacs_hook;
419 Lisp_Object Qsave_buffers_kill_emacs;
420
421 extern Lisp_Object Vlisp_EXEC_SUFFIXES;
422 \f
423 /* Ben's capsule summary about expected and unexpected exits from SXEmacs.
424
425    Expected exits occur when the user directs SXEmacs to exit, for example
426    by pressing the close button on the only frame in SXEmacs, or by typing
427    C-x C-c.  This runs `save-buffers-kill-emacs', which saves any necessary
428    buffers, and then exits using the primitive `kill-emacs'.
429
430    However, unexpected exits occur in a few different ways:
431
432      -- a memory access violation or other hardware-generated exception
433         occurs.  This is the worst possible problem to deal with, because
434         the fault can occur while SXEmacs is in any state whatsoever, even
435         quite unstable ones.  As a result, we need to be *extremely* careful
436         what we do.
437      -- we are using one X display (or if we've used more, we've closed the
438         others already), and some hardware or other problem happens and
439         suddenly we've lost our connection to the display.  In this situation,
440         things are not so dire as in the last one; our code itself isn't
441         trashed, so we can continue execution as normal, after having set
442         things up so that we can exit at the appropriate time.  Our exit
443         still needs to be of the emergency nature; we have no displays, so
444         any attempts to use them will fail.  We simply want to auto-save
445         (the single most important thing to do during shut-down), do minimal
446         cleanup of stuff that has an independent existence outside of SXEmacs,
447         and exit.
448
449         Currently, both unexpected exit scenarios described above set
450         preparing_for_armageddon to indicate that nonessential and possibly
451         dangerous things should not be done, specifically:
452
453         -- no garbage collection.
454         -- no hooks are run.
455         -- no messages of any sort from autosaving.
456         -- autosaving tries harder, ignoring certain failures.
457         -- existing frames are not deleted.
458
459         (Also, all places that set preparing_for_armageddon also
460         set dont_check_for_quit.  This happens separately because it's
461         also necessary to set other variables to make absolutely sure
462         no quitting happens.)
463
464         In the first scenario above (the access violation), we also set
465         fatal_error_in_progress.  This causes more things to not happen:
466
467         -- assertion failures do not abort.
468         -- printing code does not do code conversion or gettext when
469            printing to stdout/stderr.
470 */
471
472 /* Nonzero if handling a fatal error already. */
473 int fatal_error_in_progress;
474
475 /* Non-nil means we're going down, so we better not run any hooks
476    or do other non-essential stuff. */
477 int preparing_for_armageddon;
478
479 /* Nonzero means we're in an unstable situation and need to skip
480    i18n conversions and such during printing. */
481 int inhibit_non_essential_printing_operations;
482
483 static JMP_BUF run_temacs_catch;
484
485 static int run_temacs_argc;
486 static char **run_temacs_argv;
487 static char *run_temacs_args;
488 static EMACS_INT run_temacs_argv_size;
489 static EMACS_INT run_temacs_args_size;
490
491 static void shut_down_emacs(int sig, Lisp_Object stuff, int no_auto_save);
492
493 /* ------------------------------- */
494 /*  low-level debugging functions  */
495 /* ------------------------------- */
496
497 #define debugging_breakpoint()
498
499 void
500 debug_break(void)
501 {
502         debugging_breakpoint();
503 }
504
505 /* #### There must be a better way!!!! */
506
507 static JMP_BUF memory_error_jump;
508
509 #if 1
510 static SIGTYPE
511 debug_memory_error(int signum)
512 {
513         EMACS_REESTABLISH_SIGNAL(signum, debug_memory_error);
514         EMACS_UNBLOCK_SIGNAL(signum);
515         LONGJMP(memory_error_jump, 1);
516 }
517 #endif
518
519 static char dummy_char;
520
521 /* Return whether all bytes in the specified memory block can be read. */
522 int
523 debug_can_access_memory(void *ptr, Bytecount len)
524 {
525         /* Use volatile to protect variables from being clobbered by longjmp. */
526         SIGTYPE(*volatile old_sigbus) (int);
527         SIGTYPE(*volatile old_sigsegv) (int);
528         volatile int old_errno = errno;
529         volatile int retval = 1;
530
531         if (!SETJMP(memory_error_jump)) {
532 #if 1
533                 old_sigbus =
534                         (SIGTYPE(*)(int))signal(SIGBUS, debug_memory_error);
535                 old_sigsegv =
536                         (SIGTYPE(*)(int))signal(SIGSEGV, debug_memory_error);
537 #endif
538                 /*
539                  * Examine memory pool at PTR, trying to cheat
540                  * compiler's optimisations.
541                  */
542                 while (len-- > 0) {
543                         dummy_char = ((char*)ptr)[len];
544                 }
545         } else {
546                 retval = 0;
547         }
548         signal(SIGBUS, old_sigbus);
549         signal(SIGSEGV, old_sigsegv);
550         errno = old_errno;
551
552         return retval;
553 }
554
555 #ifdef DEBUG_SXEMACS
556
557 DEFUN("force-debugging-signal", Fforce_debugging_signal, 0, 1, 0, /*
558 Cause SXEmacs to enter the debugger.
559 On some systems, there may be no way to do this gracefully; if so,
560 nothing happens unless ABORT is non-nil, in which case SXEmacs will
561 abort() -- a sure-fire way to immediately get back to the debugger,
562 but also a sure-fire way to kill SXEmacs (and dump core on Unix
563 systems)!
564 */
565       (abort_))
566 {
567         debugging_breakpoint();
568         if (!NILP(abort_))
569                 abort();
570         return Qnil;
571 }
572
573 #endif                          /* DEBUG_SXEMACS */
574
575 static void
576 ensure_no_quitting_from_now_on(void)
577 {
578         /* make sure no quitting from now on!! */
579         dont_check_for_quit = 1;
580         Vinhibit_quit = Qt;
581         Vquit_flag = Qnil;
582 }
583
584 #if 1
585 /* Handle bus errors, illegal instruction, etc. */
586 SIGTYPE
587 fatal_error_signal(int sig)
588 {
589         fatal_error_in_progress++;
590         inhibit_non_essential_printing_operations = 1;
591         preparing_for_armageddon = 1;
592
593         ensure_no_quitting_from_now_on();
594
595         /* Unblock the signal so that if the same signal gets sent in the
596            code below, we avoid a deadlock. */
597         EMACS_UNBLOCK_SIGNAL(sig);
598
599         /* Only try auto-saving first time through.  If we crash in auto-saving,
600            don't do it again. */
601         if (fatal_error_in_progress == 1) {
602                 Fdo_auto_save(Qt, Qnil);        /* do this before anything hazardous */
603                 /* Do this so that the variable has the same value of 2 regardless of
604                    whether we made it through auto-saving correctly. */
605                 fatal_error_in_progress++;
606         } else if (fatal_error_in_progress == 2)
607                 stderr_out("WARNING: Unable to auto-save your files properly.\n"
608                            "Some or all may in fact have been auto-saved.\n"
609                            "\n");
610
611         /* Now, reset our signal handler, so the next time, we just die.
612            Don't do this before auto-saving. */
613         signal(sig, SIG_DFL);
614
615         /* Keep in mind that there's more than one signal that we can crash
616            on. */
617         /* If fatal error occurs in code below, avoid infinite recursion.  */
618         if (fatal_error_in_progress <= 2) {
619                 shut_down_emacs(sig, Qnil, 1);
620                 stderr_out("\nLisp backtrace follows:\n\n");
621                 Fbacktrace(Qexternal_debugging_output, Qt);
622 # if 0                          /* This is evil, rarely useful, and causes grief in some cases. */
623                 /* Check for Sun-style stack printing via /proc */
624                 {
625                         const char *pstack = "/usr/proc/bin/pstack";
626                         if (access(pstack, X_OK) == 0) {
627                                 char buf[100];
628                                 int sz = snprintf(buf, sizeof(buf), "%s %d >&2", pstack,
629                                         (int)getpid());
630                                 stderr_out("\nC backtrace follows:\n"
631                                            "(A real debugger may provide better information)\n\n");
632                                 if ( sz >= 0 && sz < sizeof(buf)) {
633                                         sz = system(buf);
634                                         if ( sz != 0 )
635                                                 stderr_out("\nStacktrace utility execution error code: %d\n", sz);
636                                 } else {
637                                         stderr_out("\nCould not build command line for stacktrace utility.\n");
638                                 }
639                         }
640                 }
641 # endif
642         }
643         /* Signal the same code; this time it will really be fatal. */
644         kill(getpid(), sig);
645         SIGRETURN;
646 }
647 #endif
648
649 \f
650 #ifdef SIGDANGER
651
652 /* Handler for SIGDANGER.  */
653 SIGTYPE
654 memory_warning_signal(int sig)
655 {
656         /* #### bad bad bad; this function shouldn't do anything except
657            set a flag, or weird corruption could happen. */
658         signal(sig, memory_warning_signal);
659
660         malloc_warning
661             (GETTEXT
662              ("Operating system warns that virtual memory is running low.\n"));
663
664         /* It might be unsafe to call do_auto_save now.  */
665         force_auto_save_soon();
666 }
667 #endif                          /* SIGDANGER */
668 \f
669 /* Code for dealing with Lisp access to the Unix command line */
670
671 static Lisp_Object
672 make_arg_list_1(int argc, Extbyte ** argv, int skip_args)
673 {
674         Lisp_Object result = Qnil;
675         REGISTER int i;
676
677         for (i = argc - 1; i >= 0; i--) {
678                 if (i != 0 && i <= skip_args)
679                         continue;
680
681                 result = Fcons(build_ext_string(argv[i], Qcommand_argument_encoding), result);
682         }
683         return result;
684 }
685
686 Lisp_Object
687 make_arg_list(int argc, Extbyte ** argv)
688 {
689         return make_arg_list_1(argc, argv, 0);
690 }
691
692 /* Calling functions are also responsible for calling free_argc_argv
693    when they are done with the generated list. */
694 void
695 make_argc_argv(Lisp_Object argv_list, int *argc, Extbyte *** argv)
696 {
697         Lisp_Object next;
698         int n = XINT(Flength(argv_list));
699         REGISTER int i;
700         *argv = (Extbyte **) malloc((n + 1) * sizeof(Extbyte *));
701
702         for (i = 0, next = argv_list; i < n; i++, next = XCDR(next)) {
703                 const Extbyte *temp;
704                 CHECK_STRING(XCAR(next));
705
706                 LISP_STRING_TO_EXTERNAL(XCAR(next), temp,
707                                         Qcommand_argument_encoding);
708                 (*argv)[i] = strdup(temp);
709         }
710         (*argv)[n] = 0;
711         *argc = i;
712 }
713
714 void free_argc_argv(Extbyte ** argv)
715 {
716         int elt = 0;
717
718         while (argv[elt]) {
719                 free(argv[elt]);
720                 elt++;
721         }
722         free(argv);
723 }
724
725 static void init_cmdargs(int argc, Extbyte ** argv, int skip_args)
726 {
727         initial_argv = argv;
728         initial_argc = argc;
729
730         Vcommand_line_args = make_arg_list_1(argc, argv, skip_args);
731 }
732
733 DEFUN("invocation-name", Finvocation_name, 0, 0, 0, /*
734 Return the program name that was used to run SXEmacs.
735 Any directory names are omitted.
736 */
737       ())
738 {
739         return Fcopy_sequence(Vinvocation_name);
740 }
741
742 DEFUN("invocation-directory", Finvocation_directory, 0, 0, 0, /*
743 Return the directory name in which the Emacs executable was located.
744 */
745       ())
746 {
747         return Fcopy_sequence(Vinvocation_directory);
748 }
749 \f
750 #ifdef I18N4
751                                 /* #### - don't know why I18N4 on SunOS/JLE
752                                    can't deal with this.  It's a potential
753                                    bug that needs to be looked at. */
754 # undef RUN_TIME_REMAP
755 #endif
756
757 /* Test whether the next argument in ARGV matches SSTR or a prefix of
758    LSTR (at least MINLEN characters).  If so, then if VALPTR is non-null
759    (the argument is supposed to have a value) store in *VALPTR either
760    the next argument or the portion of this one after the equal sign.
761    ARGV is read starting at position *SKIPPTR; this index is advanced
762    by the number of arguments used.
763
764    Too bad we can't just use getopt for all of this, but we don't have
765    enough information to do it right.  */
766
767 static int
768 argmatch(char **argv, int argc, char *sstr, char *lstr,
769          int minlen, char **valptr, int *skipptr)
770 {
771         char *p = NULL;
772         int arglen;
773         char *arg;
774
775         /* Don't access argv[argc]; give up in advance.  */
776         if (argc <= *skipptr + 1)
777                 return 0;
778
779         arg = argv[*skipptr + 1];
780         if (arg == NULL)
781                 return 0;
782         if (strcmp(arg, sstr) == 0) {
783                 if (valptr != NULL) {
784                         *valptr = argv[*skipptr + 2];
785                         *skipptr += 2;
786                 } else
787                         *skipptr += 1;
788                 return 1;
789         }
790         arglen = (valptr != NULL && (p = strchr(arg, '=')) != NULL
791                   ? p - arg : (int)strlen(arg));
792         if (lstr == 0 || arglen < minlen || strncmp(arg, lstr, arglen) != 0)
793                 return 0;
794         else if (valptr == NULL) {
795                 *skipptr += 1;
796                 return 1;
797         } else if (p != NULL) {
798                 *valptr = p + 1;
799                 *skipptr += 1;
800                 return 1;
801         } else if (argv[*skipptr + 2] != NULL) {
802                 *valptr = argv[*skipptr + 2];
803                 *skipptr += 2;
804                 return 1;
805         } else {
806                 return 0;
807         }
808 }
809
810 static int
811 make_docfile(int c, char **v)
812 {
813 #define make_docfile_prog       "make-docfile\0"
814 #define make_docfile_opt        "--make-docfile"
815         /* C99 we need you */
816         size_t edlen = XSTRING_LENGTH(Vexec_directory);
817         char mdocfile[edlen+countof(make_docfile_prog)];
818         char **newargv = xnew_array_and_zero(char*, c), **p;
819         int  ret = -1;
820
821         /* set up the program call */
822         xstrncpy(mdocfile,
823                  (char*)XSTRING_DATA(Vexec_directory),
824                  XSTRING_LENGTH(Vexec_directory));
825         xstrncpy(mdocfile+XSTRING_LENGTH(Vexec_directory),
826                  make_docfile_prog, countof(make_docfile_prog));
827
828         /* find the --make-docfile option */
829         for (p = v; *p; p++) {
830                 if (strncmp(*p, make_docfile_opt,
831                             countof(make_docfile_opt)) == 0) {
832                         p++;
833                         break;
834                 }
835         }
836
837         /* fill the new argv array */
838         newargv[0] = make_docfile_prog;
839         for (char **o = p, **n = &newargv[1]; *o;) {
840                 *n++ = *o++;
841         }
842         ret = execv(mdocfile, newargv);
843         xfree(newargv);
844         return ret;
845 }
846
847 static inline void*
848 __get_sp(void)
849 {
850         void *sp = 0;
851
852 #if 0
853 /* we need some checks whether this is supported! */
854         __asm__ __volatile__ (
855                 "movl %%esp, %[stkptr]\n\t"
856                 : [stkptr] "=m" (sp));
857 #endif
858
859         return sp;
860 }
861
862 static size_t
863 __sys_stk_sz(void)
864 {
865 /* return the stack size limit */
866 #if defined HAVE_GETRLIMIT64
867         struct rlimit64 rlim;
868         (void)getrlimit64(RLIMIT_STACK, &rlim);
869 #elif defined HAVE_GETRLIMIT
870         struct rlimit rlim;
871         (void)getrlimit(RLIMIT_STACK, &rlim);
872 #else
873         /* bollocks, maybe just a small one? 64k? */
874         struct {size_t rlim_cur;} rlim = {65536};
875 #endif
876         return rlim.rlim_cur;
877 }
878
879
880 /* Make stack traces always identify version + configuration */
881 #define main_1 STACK_TRACE_EYE_CATCHER
882
883 /* This function is not static, so that the compiler is less likely to
884    inline it, which would make it not show up in stack traces.
885
886    The restart argument is a flag that indicates that main_1 is now
887    being called for the second time in this invocation of sxemacs; this can
888    only happen in an sxemacs that is not loaded with dumped data (temacs
889    with the conventional dumper or sxemacs -nd with the pdumper).   See
890    Frun_emacs_from_temacs().
891
892    restart interacts with initialized as follows (per Olivier Galibert):
893
894      It's perverted.
895
896      initialized==0 => temacs
897      initialized!=0 && restart!=0 => run-temacs
898      initialized!=0 && restart==0 => sxemacs/post pdump_load()
899 */
900 DECLARE_DOESNT_RETURN(main_1(int, char **, char **, int));
901 DOESNT_RETURN main_1(int argc, char **argv, char **envp, int restart)
902 {
903         char stack_bottom_variable;
904         int skip_args = 0;
905         Lisp_Object load_me;
906         int inhibit_window_system;
907 #ifdef NeXT
908         extern int malloc_cookie;
909 #endif
910
911 #if (!defined (SYSTEM_MALLOC) && !defined (HAVE_LIBMCHECK)      \
912      && !defined (DOUG_LEA_MALLOC))
913         /* Make sure that any libraries we link against haven't installed a
914            hook for a gmalloc of a potentially incompatible version. */
915         /* If we're using libmcheck, the hooks have already been initialized, */
916         /* don't touch them. -slb */
917         __malloc_hook = NULL;
918         __realloc_hook = NULL;
919         __free_hook = NULL;
920 #endif  /* not SYSTEM_MALLOC or HAVE_LIBMCHECK or DOUG_LEA_MALLOC */
921
922         noninteractive = 0;
923         inhibit_non_essential_printing_operations = 1;
924
925 #ifdef NeXT
926         /* 19-Jun-1995 -baw
927          * NeXT secret magic, ripped from Emacs-for-NS by Carl Edman
928          * <cedman@princeton.edu>.  Note that even Carl doesn't know what this
929          * does; it was provided by NeXT, and it presumable makes NS's mallocator
930          * work with dumping.  But malloc_jumpstart() and malloc_freezedry() in
931          * unexnext.c are both completely undocumented, even in NS header files!
932          * But hey, it solves all NS related memory problems, so who's
933          * complaining? */
934         if (initialized && malloc_jumpstart(malloc_cookie) != 0)
935                 stderr_out("malloc jumpstart failed!\n");
936 #endif                          /* NeXT */
937
938         /*
939            #if defined (GNU_MALLOC) && \
940            defined (ERROR_CHECK_MALLOC) && \
941            !defined (HAVE_LIBMCHECK)
942          */
943 #if defined(LOSING_GCC_DESTRUCTOR_FREE_BUG)
944         /* Prior to SXEmacs 21, this was `#if 0'ed out.  */
945         /* I'm enabling this because it is the only reliable way I've found to */
946         /* prevent a very annoying problem where GCC will attempt to free(3) */
947         /* memory at exit() and cause a coredump. */
948 #if 0
949         init_free_hook();
950 #endif
951 #endif
952
953         sort_args(argc, argv);
954
955 #if defined(_SCO_DS)
956         environ = envp;
957 #endif
958
959         /* Record (approximately) where the stack begins.  */
960         stack_bottom = &stack_bottom_variable;
961         /* and determine the system's stack limit */
962         sys_stk_sz = __sys_stk_sz();
963
964 #ifdef USG_SHARED_LIBRARIES
965         if (bss_end)
966                 brk((void *)bss_end);
967 #endif
968
969         clearerr(stdin);
970
971 #if defined (HAVE_MMAP) && defined (REL_ALLOC)
972         /* ralloc can only be used if using the GNU memory allocator. */
973         init_ralloc();
974 #elif defined (REL_ALLOC) && !defined(DOUG_LEA_MALLOC)
975         if (initialized)
976                 init_ralloc();
977 #endif
978
979 #ifdef HAVE_SOCKS
980         if (initialized)
981                 SOCKSinit(argv[0]);
982 #endif                          /* HAVE_SOCKS */
983
984 #if !defined SYSTEM_MALLOC && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
985         if (!initialized)
986                 /* Arrange to get warning messages as memory fills up.  */
987                 memory_warnings(0, malloc_warning);
988 #endif                          /* not SYSTEM_MALLOC */
989
990 #ifdef SET_EMACS_PRIORITY
991         if (emacs_priority != 0)
992                 nice(-emacs_priority);
993         setuid(getuid());
994 #endif                          /* SET_EMACS_PRIORITY */
995
996 #ifdef EXTRA_INITIALIZE
997         EXTRA_INITIALIZE;
998 #endif
999
1000 #ifdef HAVE_WINDOW_SYSTEM
1001         inhibit_window_system = 0;
1002 #else
1003         inhibit_window_system = 1;
1004 #endif
1005
1006         /* Handle the --make-docfile argument */
1007         if (argmatch(argv, argc,
1008                      "--make-docfile", 0, 9, NULL, &skip_args)) {
1009
1010                 /* we need load the dump file as the exec-directory is in
1011                    there */
1012                 if (UNLIKELY(!pdump_load(argv[0]))) {
1013                         exit(1);
1014                 }
1015
1016                 exit(make_docfile(argc, argv));
1017         }
1018
1019         /* Handle the -sd/--show-dump-id switch, which means show the hex
1020            dump_id and quit */
1021         if (argmatch(argv, argc,
1022                      "-sd", "--show-dump-id",
1023                      9, NULL, &skip_args)) {
1024 #ifdef PDUMP
1025                 printf("%08x\n", dump_id);
1026 #else
1027                 printf
1028                     ("Portable dumper not configured; -sd just forces exit.\n");
1029 #endif
1030                 exit(0);
1031         }
1032
1033         /* Handle the -t switch, which specifies filename to use as terminal */
1034         {
1035                 char *term;
1036                 if (argmatch
1037                     (argv, argc, "-t", "--terminal", 4, &term, &skip_args)) {
1038                         int tdesc = -1;
1039 #ifdef HAVE_TTYNAME
1040                         stderr_out("Opening for terminal usage %s (current: %s)\n", term, ttyname(0));
1041 #else
1042                         stderr_out("Opening for terminal usage %s\n", term, ttyname(0));
1043 #endif
1044 #ifdef HAVE_DUP2
1045                         tdesc = raw_open(term, O_RDWR | OPEN_BINARY, 2);
1046                         if (tdesc < 0)
1047                                 fatal("%s: %s", term, strerror(errno));
1048                         /* Request dup into fd 0 */
1049                         if ( dup2(tdesc,0) < 0 )
1050                                 fatal("%s: %s", term, strerror(errno));
1051                         stderr_out("Dup(0) ok\n");
1052                         /* Requesr dup into fd 1 */
1053                         if ( dup2(tdesc,1) < 0 )
1054                                 fatal("%s: %s", term, strerror(errno));
1055                         close(tdesc);
1056 #else
1057                         close(0);
1058                         close(1);
1059                         tdesc = raw_open(term, O_RDWR | OPEN_BINARY, 2);
1060                         if (tdesc < 0)
1061                                 fatal("%s: %s", term, strerror(errno));
1062                         assert(tdesc==0);
1063                         tdesc = dup(0);
1064                         if ( tdesc < 0) {
1065                                 fatal("dup failed %s: %s", term, strerror(errno));
1066                         }
1067                         assert(tdesc==1);
1068 #endif
1069 #ifdef HAVE_ISATTY
1070                         if (!isatty(0)) {
1071                                 fatal("%s: not a tty", term);
1072                         }
1073 #endif
1074 #ifdef HAVE_TTYNAME
1075                         stderr_out("Using tty %s\n", ttyname(0));
1076 #else
1077                         stderr_out("Using %tty s\n", term);
1078 #endif
1079                         inhibit_window_system = 1;      /* -t => -nw
1080                                                          * */
1081                 }
1082         }
1083
1084         /* Handle the --no-dump-file/-nd switch, which means don't
1085          * load the dump file (ignored when not using pdump) */
1086         if (argmatch(argv, argc, "-nd", "--no-dump-file", 7,
1087                      NULL, &skip_args)) {
1088                 nodumpfile = 1;
1089         }
1090
1091         if (argmatch(argv, argc, "-ct", "--color-terminal", 5,
1092                      NULL, &skip_args)) {
1093                 assume_colorterm = 1;
1094         }
1095
1096         /* Handle -nw switch */
1097         if (argmatch(argv, argc, "-nw", "--no-windows", 6, NULL, &skip_args))
1098                 inhibit_window_system = 1;
1099
1100         /* Handle the -batch switch, which means don't do interactive display */
1101         if (argmatch(argv, argc, "-batch", "--batch", 5, NULL, &skip_args)) {
1102 #if 0                           /* I don't think this is correct. */
1103                 inhibit_autoloads = 1;
1104 #endif
1105                 noninteractive = 1;
1106         }
1107
1108         if (argmatch(argv, argc, "-debug-paths", "--debug-paths",
1109                      11, NULL, &skip_args))
1110                 debug_paths = 1;
1111
1112         /* Partially handle -no-autoloads, -no-early-packages and -vanilla.
1113            Packages */
1114         /* are searched prior to the rest of the command line being parsed in */
1115         /* startup.el */
1116         if (argmatch(argv, argc, "-no-early-packages", "--no-early-packages",
1117                      6, NULL, &skip_args)) {
1118                 inhibit_early_packages = 1;
1119                 skip_args--;
1120         }
1121 #if defined WITH_EMODULES && defined HAVE_EMODULES
1122         if (argmatch(argv, argc, "-no-site-modules", "--no-site-modules",
1123                      9, NULL, &skip_args)) {
1124                 inhibit_site_modules = 1;
1125                 skip_args--;
1126         }
1127 #else
1128         inhibit_site_modules = 1;
1129 #endif
1130         if (argmatch(argv, argc, "-vanilla", "--vanilla", 7, NULL, &skip_args)) {
1131                 inhibit_early_packages = 1;
1132                 skip_args--;
1133         }
1134
1135         if (argmatch(argv, argc, "-no-autoloads", "--no-autoloads",
1136                      7, NULL, &skip_args)) {
1137                 /* Inhibit everything */
1138                 inhibit_autoloads = 1;
1139                 skip_args--;
1140         }
1141
1142         if (argmatch(argv, argc, "-debug-paths", "--debug-paths",
1143                      6, NULL, &skip_args)) {
1144                 debug_paths = 1;
1145                 skip_args--;
1146         }
1147
1148         /* Partially handle the -version and -help switches: they imply -batch,
1149            but are not removed from the list. */
1150         if (argmatch(argv, argc, "-help", "--help", 3, NULL, &skip_args))
1151                 noninteractive = 1, skip_args--;
1152
1153         if (argmatch(argv, argc, "-version", "--version", 3, NULL, &skip_args)
1154             || argmatch(argv, argc, "-V", 0, 2, NULL, &skip_args))
1155                 noninteractive = 1, skip_args--;
1156
1157         /* Now, figure out which type of console is our first console. */
1158
1159         display_arg = 0;
1160
1161         if (noninteractive)
1162                 display_use = "stream";
1163         else
1164                 display_use = "tty";
1165
1166 #ifndef HAVE_TTY
1167         if (inhibit_window_system && !noninteractive)
1168                 fatal("Sorry, this SXEmacs was not compiled with TTY support");
1169 #endif
1170
1171 #ifdef HAVE_WINDOW_SYSTEM
1172         /* Stupid kludge to catch command-line display spec.  We can't
1173            handle this argument entirely in window-system-dependent code
1174            because we don't even know which window-system-dependent code
1175            to run until we've recognized this argument.  */
1176         if (!inhibit_window_system && !noninteractive) {
1177 #ifdef HAVE_X_WINDOWS
1178                 char *dpy = 0;
1179                 int count_before = skip_args;
1180
1181                 if (argmatch(argv, argc, "-d", "--display", 3, &dpy, &skip_args)
1182                     || argmatch(argv, argc, "-display", 0, 3, &dpy,
1183                                 &skip_args)) {
1184                         display_arg = 1;
1185                         display_use = "x";
1186                 }
1187                 /* If we have the form --display=NAME,
1188                    convert it into  -d name.
1189                    This requires inserting a new element into argv.  */
1190                 if (dpy != 0 && skip_args - count_before == 1) {
1191                         char **new =
1192                             (char **)xmalloc(sizeof(char *) * (argc + 2));
1193                         int j;
1194
1195                         for (j = 0; j < count_before + 1; j++)
1196                                 new[j] = argv[j];
1197                         new[count_before + 1] = "-d";
1198                         new[count_before + 2] = dpy;
1199                         for (j = count_before + 2; j < argc; j++)
1200                                 new[j + 1] = argv[j];
1201                         argv = new;
1202                         argc++;
1203                 }
1204                 /* Change --display to -d, when its arg is separate.  */
1205                 else if (dpy != 0 && skip_args > count_before
1206                          && argv[count_before + 1][1] == '-')
1207                         argv[count_before + 1] = "-d";
1208
1209                 /* Don't actually discard this arg.  */
1210                 skip_args = count_before;
1211
1212                 /* If there is a non-empty environment var DISPLAY, set
1213                    `display_use', but not `display_arg', which is only to be set
1214                    if the display was specified on the command line. */
1215                 if ((dpy = getenv("DISPLAY")) && dpy[0])
1216                         display_use = "x";
1217
1218 #endif                          /* HAVE_X_WINDOWS */
1219         }
1220 #endif                          /* HAVE_WINDOW_SYSTEM */
1221
1222         noninteractive1 = noninteractive;
1223
1224         /****** Now initialize everything *******/
1225
1226         /* First, do really basic environment initialization -- catching signals
1227            and the like.  These functions have no dependence on any part of
1228            the Lisp engine and need to be done both at dump time and at run time. */
1229
1230         init_signals_very_early();
1231         init_data_very_early(); /* Catch math errors. */
1232 #ifdef HAVE_FPFLOAT
1233         init_floatfns_very_early();     /* Catch floating-point math errors. */
1234 #endif
1235         init_process_times_very_early();        /* Initialize our process timers.
1236                                                    As early as possible, of course,
1237                                                    so we can be fairly accurate. */
1238         init_intl_very_early(); /* set up the locale and domain for gettext and
1239                                    such. */
1240
1241         /* Now initialize the Lisp engine and the like.  Done only during
1242            dumping.  No dependence on anything that may be in the user's
1243            environment when the dumped SXEmacs is run.
1244
1245            We try to do things in an order that minimizes the non-obvious
1246            dependencies between functions. */
1247
1248         /* purify_flag 1 is correct even if CANNOT_DUMP.
1249          * loadup.el will set to nil at end. */
1250
1251         purify_flag = 0;
1252 #ifdef PDUMP
1253         if (restart) {
1254                 initialized = 1;
1255         } else if (nodumpfile) {
1256                 initialized = 0;
1257                 purify_flag = 1;
1258         } else {
1259
1260                 /* Keep command options from getting stomped.
1261
1262                    Some LISP-visible options are changed by SXEmacs _after_ the data is
1263                    dumped in building a --pdump SXEmacs, but _before_ it is restored in
1264                    normal operation.  Thus the restored values overwrite the values
1265                    SXEmacs is getting at run-time.  Such variables must be saved here,
1266                    and restored after loading the dumped data.
1267
1268                    Boy, this is ugly, but how else to do it?
1269                  */
1270
1271                 /* noninteractive1 is saved in noninteractive, which isn't
1272                    LISP-visible */
1273                 int inhibit_early_packages_save = inhibit_early_packages;
1274                 int inhibit_autoloads_save = inhibit_autoloads;
1275                 int debug_paths_save = debug_paths;
1276                 int inhibit_site_modules_save = inhibit_site_modules;
1277
1278                 initialized = pdump_load(argv[0]);
1279
1280                 /* Now unstomp everything */
1281                 noninteractive1 = noninteractive;
1282                 inhibit_early_packages = inhibit_early_packages_save;
1283                 inhibit_autoloads = inhibit_autoloads_save;
1284                 debug_paths = debug_paths_save;
1285                 inhibit_site_modules = inhibit_site_modules_save;
1286
1287                 if (initialized)
1288                         run_temacs_argc = -1;
1289                 else
1290                         purify_flag = 1;
1291         }
1292 #else
1293         if (!initialized)
1294                 purify_flag = 1;
1295 #endif
1296
1297         if (!initialized) {
1298                 /* Initialize things so that new Lisp objects
1299                    can be created and objects can be staticpro'd.
1300                    Must be basically the very first thing done
1301                    because pretty much all of the initialization
1302                    routines below create new objects. */
1303                 init_alloc_once_early();
1304
1305                 /* Initialize Qnil, Qt, Qunbound, and the
1306                    obarray.  After this, symbols can be
1307                    interned.  This depends on init_alloc_once_early(). */
1308                 init_symbols_once_early();
1309
1310                 /* Declare the basic symbols pertaining to errors,
1311                    So that DEFERROR*() can be called. */
1312                 init_errors_once_early();
1313
1314                 /* Make sure that opaque pointers can be created. */
1315                 init_opaque_once_early();
1316
1317                 /* Now declare all the symbols and define all the Lisp primitives.
1318
1319                    The *only* thing that the syms_of_*() functions are allowed to do
1320                    is call one of the following:
1321
1322                    INIT_LRECORD_IMPLEMENTATION()
1323                    defsymbol(), DEFSYMBOL(), or DEFSYMBOL_MULTIWORD_PREDICATE()
1324                    defsubr() (i.e. DEFSUBR)
1325                    deferror(), DEFERROR(), or DEFERROR_STANDARD()
1326                    defkeyword() or DEFKEYWORD()
1327
1328                    Order does not matter in these functions.
1329                  */
1330
1331                 syms_of_abbrev();
1332                 syms_of_alloc();
1333                 syms_of_buffer();
1334                 syms_of_bytecode();
1335                 syms_of_callint();
1336                 syms_of_callproc();
1337                 syms_of_casefiddle();
1338                 syms_of_casetab();
1339                 syms_of_chartab();
1340                 syms_of_cmdloop();
1341                 syms_of_cmds();
1342                 syms_of_console();
1343                 syms_of_data();
1344 #ifdef DEBUG_SXEMACS
1345                 syms_of_debug();
1346                 syms_of_tests();
1347 #endif                          /* DEBUG_SXEMACS */
1348                 syms_of_device();
1349 #ifdef HAVE_DIALOGS
1350                 syms_of_dialog();
1351 #endif
1352                 syms_of_dired();
1353                 syms_of_doc();
1354                 syms_of_editfns();
1355                 syms_of_elhash();
1356                 syms_of_emacs();
1357                 syms_of_eval();
1358 #ifdef HAVE_X_WINDOWS
1359                 syms_of_event_Xt();
1360 #endif
1361 #ifdef HAVE_DRAGNDROP
1362                 syms_of_dragdrop();
1363 #endif
1364 #ifdef EF_USE_ASYNEQ
1365                 syms_of_event_queue();
1366                 syms_of_workers();
1367                 syms_of_worker_asyneq();
1368 #endif
1369                 syms_of_event_stream();
1370                 syms_of_events();
1371                 syms_of_extents();
1372                 syms_of_faces();
1373                 syms_of_fileio();
1374 #ifdef CLASH_DETECTION
1375                 syms_of_filelock();
1376 #endif                          /* CLASH_DETECTION */
1377                 syms_of_floatfns();
1378                 syms_of_fns();
1379                 syms_of_font_lock();
1380                 syms_of_frame();
1381                 syms_of_general();
1382                 syms_of_glyphs();
1383                 syms_of_glyphs_eimage();
1384                 syms_of_glyphs_widget();
1385                 syms_of_gui();
1386                 syms_of_gutter();
1387                 syms_of_indent();
1388                 syms_of_intl();
1389                 syms_of_keymap();
1390                 syms_of_lread();
1391                 syms_of_macros();
1392                 syms_of_marker();
1393                 syms_of_md5();
1394 #ifdef HAVE_DATABASE
1395                 syms_of_database();
1396 #endif
1397 #ifdef HAVE_MENUBARS
1398                 syms_of_menubar();
1399 #endif
1400                 syms_of_media();
1401                 syms_of_minibuf();
1402                 syms_of_dynacat();
1403 #if defined WITH_EMODULES && defined HAVE_EMODULES && 0
1404                 syms_of_module();
1405 #elif defined WITH_EMODULES && defined HAVE_EMODULES
1406                 syms_of_emodng();
1407 #endif
1408                 syms_of_objects();
1409                 syms_of_print();
1410 #if !defined (NO_SUBPROCESSES)
1411                 syms_of_process();
1412 #endif
1413                 syms_of_profile();
1414 #if defined (HAVE_MMAP) && defined (REL_ALLOC) && !defined(DOUG_LEA_MALLOC)
1415                 syms_of_ralloc();
1416 #endif                          /* HAVE_MMAP && REL_ALLOC */
1417                 syms_of_rangetab();
1418                 syms_of_redisplay();
1419                 syms_of_search();
1420                 syms_of_select();
1421                 syms_of_signal();
1422                 syms_of_sound();
1423                 syms_of_specifier();
1424                 syms_of_symbols();
1425                 syms_of_syntax();
1426 #ifdef HAVE_SCROLLBARS
1427                 syms_of_scrollbar();
1428 #endif
1429 #ifdef HAVE_TOOLBARS
1430                 syms_of_toolbar();
1431 #endif
1432                 syms_of_undo();
1433                 syms_of_widget();
1434                 syms_of_window();
1435
1436 #ifdef HAVE_TTY
1437                 syms_of_console_tty();
1438                 syms_of_device_tty();
1439                 syms_of_objects_tty();
1440 #endif
1441
1442 #ifdef HAVE_X_WINDOWS
1443 #ifdef HAVE_BALLOON_HELP
1444                 syms_of_balloon_x();
1445 #endif
1446                 syms_of_device_x();
1447 #ifdef HAVE_DIALOGS
1448                 syms_of_dialog_x();
1449 #endif
1450                 syms_of_frame_x();
1451                 syms_of_glyphs_x();
1452                 syms_of_objects_x();
1453 #ifdef HAVE_MENUBARS
1454                 syms_of_menubar_x();
1455 #endif
1456                 syms_of_select_x();
1457 #if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_DIALOGS) || defined (HAVE_TOOLBARS)
1458                 syms_of_gui_x();
1459 #endif
1460 #ifdef HAVE_XIM
1461 #ifdef XIM_XLIB
1462                 syms_of_input_method_xlib();
1463 #endif
1464 #endif                          /* HAVE_XIM */
1465 #endif                          /* HAVE_X_WINDOWS */
1466
1467 #ifdef MULE
1468                 syms_of_mule();
1469                 syms_of_mule_ccl();
1470                 syms_of_mule_charset();
1471 #endif
1472 #ifdef FILE_CODING
1473                 syms_of_file_coding();
1474 #endif
1475 #ifdef MULE
1476 #ifdef HAVE_WNN
1477                 syms_of_mule_wnn();
1478 #endif
1479 #ifdef HAVE_CANNA
1480                 syms_of_mule_canna();
1481 #endif                          /* HAVE_CANNA */
1482 #endif                          /* MULE */
1483
1484 #ifdef SYMS_SYSTEM
1485                 SYMS_SYSTEM;
1486 #endif
1487
1488 #ifdef SYMS_MACHINE
1489                 SYMS_MACHINE;
1490 #endif
1491
1492                 /*
1493                    #if defined (GNU_MALLOC) && \
1494                    defined (ERROR_CHECK_MALLOC) && \
1495                    !defined (HAVE_LIBMCHECK)
1496                  */
1497                 /* Prior to SXEmacs 21, this was `#if 0'ed out. -slb */
1498 #if defined (LOSING_GCC_DESTRUCTOR_FREE_BUG)
1499                 syms_of_free_hook();
1500 #endif
1501
1502 #ifdef SUNPRO
1503                 syms_of_sunpro();
1504 #endif
1505
1506 #ifdef HAVE_LDAP
1507                 syms_of_eldap();
1508 #endif
1509
1510 #ifdef HAVE_GPM
1511                 syms_of_gpmevent();
1512 #endif
1513
1514 #ifdef HAVE_POSTGRESQL
1515                 syms_of_postgresql();
1516 #endif
1517
1518 #ifdef HAVE_OPENSSL
1519                 syms_of_openssl();
1520 #endif
1521
1522 #ifdef WITH_NUMBER_TYPES
1523                 syms_of_ent();
1524 #endif
1525
1526 #ifdef HAVE_LIBFFI
1527                 syms_of_ffi();
1528 #endif
1529
1530                 syms_of_dllist();
1531                 syms_of_skiplist();
1532                 syms_of_bloom();
1533
1534                 /* Now create the subtypes for the types that have them.
1535                    We do this before the vars_*() because more symbols
1536                    may get initialized here. */
1537
1538                 /* Now initialize the console types and associated symbols.
1539                    Other than the first function below, the functions may
1540                    make exactly the following function/macro calls:
1541
1542                    INITIALIZE_CONSOLE_TYPE()
1543                    CONSOLE_HAS_METHOD()
1544
1545                    For any given console type, the former macro must be called
1546                    before the any calls to the latter macro. */
1547
1548                 console_type_create();
1549
1550                 console_type_create_stream();
1551
1552 #ifdef HAVE_TTY
1553                 console_type_create_tty();
1554                 console_type_create_device_tty();
1555                 console_type_create_frame_tty();
1556                 console_type_create_objects_tty();
1557                 console_type_create_redisplay_tty();
1558 #endif
1559
1560 #ifdef HAVE_X_WINDOWS
1561                 console_type_create_x();
1562                 console_type_create_device_x();
1563                 console_type_create_frame_x();
1564                 console_type_create_glyphs_x();
1565                 console_type_create_select_x();
1566 #ifdef HAVE_MENUBARS
1567                 console_type_create_menubar_x();
1568 #endif
1569                 console_type_create_objects_x();
1570                 console_type_create_redisplay_x();
1571 #ifdef HAVE_SCROLLBARS
1572                 console_type_create_scrollbar_x();
1573 #endif
1574 #ifdef HAVE_TOOLBARS
1575                 console_type_create_toolbar_x();
1576 #endif
1577 #ifdef HAVE_DIALOGS
1578                 console_type_create_dialog_x();
1579 #endif
1580 #endif                          /* HAVE_X_WINDOWS */
1581
1582                 /* Now initialize the specifier types and associated symbols.
1583                    Other than the first function below, the functions may
1584                    make exactly the following function/macro calls:
1585
1586                    INITIALIZE_SPECIFIER_TYPE()
1587                    SPECIFIER_HAS_METHOD()
1588
1589                    For any given specifier type, the former macro must be called
1590                    before the any calls to the latter macro. */
1591
1592                 specifier_type_create();
1593
1594                 specifier_type_create_image();
1595                 specifier_type_create_gutter();
1596                 specifier_type_create_objects();
1597 #ifdef HAVE_TOOLBARS
1598                 specifier_type_create_toolbar();
1599 #endif
1600
1601                 /* Now initialize the structure types and associated symbols.
1602                    Other than the first function below, the functions may
1603                    make exactly the following function/macro calls:
1604
1605                    define_structure_type()
1606                    define_structure_type_keyword()
1607
1608                  */
1609
1610                 structure_type_create();
1611
1612                 structure_type_create_chartab();
1613                 structure_type_create_faces();
1614                 structure_type_create_rangetab();
1615                 structure_type_create_hash_table();
1616
1617                 /* Now initialize the image instantiator formats and associated symbols.
1618                    Other than the first function below, the functions may
1619                    make exactly the following function/macro calls:
1620
1621                    INITIALIZE_IMAGE_INSTANTIATOR_FORMAT()
1622                    IIFORMAT_HAS_METHOD()
1623                    IIFORMAT_VALID_KEYWORD()
1624
1625                    For any given image instantiator format, the first macro must be
1626                    called before the any calls to the other macros. */
1627
1628                 image_instantiator_format_create();
1629                 image_instantiator_format_create_glyphs_eimage();
1630                 image_instantiator_format_create_glyphs_widget();
1631 #ifdef HAVE_TTY
1632                 image_instantiator_format_create_glyphs_tty();
1633 #endif
1634 #ifdef HAVE_X_WINDOWS
1635                 image_instantiator_format_create_glyphs_x();
1636 #endif                          /* HAVE_X_WINDOWS */
1637
1638                 /* Now initialize the lstream types and associated symbols.
1639                    Other than the first function below, the functions may
1640                    make exactly the following function/macro calls:
1641
1642                    LSTREAM_HAS_METHOD()
1643
1644                  */
1645
1646                 lstream_type_create();
1647 #ifdef FILE_CODING
1648                 lstream_type_create_file_coding();
1649 #endif
1650
1651                 /* Initialize processes implementation.
1652                    The functions may make exactly the following function/macro calls:
1653
1654                    PROCESS_HAS_METHOD()
1655                  */
1656 #ifdef HAVE_UNIX_PROCESSES
1657                 process_type_create_unix();
1658 #endif
1659
1660                 /* Now initialize most variables.
1661
1662                    These functions may do exactly the following:
1663
1664                    DEFVAR_INT()
1665                    DEFVAR_LISP()
1666                    DEFVAR_BOOL()
1667                    DEFER_GETTEXT()
1668                    Dynarr_*()
1669                    Blocktype_*()
1670                    staticpro()
1671                    Fprovide(symbol)
1672                    intern()
1673                    Fput()
1674                    xmalloc()
1675                    defsymbol(), if it's absolutely necessary and you're sure that
1676                    the symbol isn't referenced anywhere else in the initialization
1677                    code
1678                    Fset() on a symbol that is unbound
1679                    assigning a symbol or constant value to a variable
1680                    using a global variable that has been initialized
1681                    earlier on in the same function
1682
1683                    Any of the object-creating functions in alloc.c: e.g.
1684
1685                    make_pure_*()
1686                    make_string()
1687                    build_string()
1688                    make_vector()
1689                    make_int()
1690                    make_extent()
1691                    alloc_lcrecord()
1692                    Fcons()
1693                    listN()
1694                    make_opaque_ptr()
1695
1696                    perhaps a few others.
1697
1698                    NB:  Initialization or assignment should not be done here to certain
1699                    variables settable from the command line.  See the comment above
1700                    the call to pdump_load() in main_1().  This caveat should only
1701                    apply to vars_of_emacs().
1702                  */
1703
1704                 /* Now allow Fprovide() statements to be made. */
1705                 init_provide_once();
1706
1707                 /* Do that before any specifier creation (esp. vars_of_glyphs()) */
1708                 vars_of_specifier();
1709
1710                 vars_of_abbrev();
1711                 vars_of_alloc();
1712                 vars_of_buffer();
1713                 vars_of_bytecode();
1714                 vars_of_callint();
1715                 vars_of_callproc();
1716                 vars_of_chartab();
1717                 vars_of_cmdloop();
1718                 vars_of_cmds();
1719                 vars_of_console();
1720                 vars_of_data();
1721 #ifdef DEBUG_SXEMACS
1722                 vars_of_debug();
1723                 vars_of_tests();
1724 #endif
1725                 vars_of_console_stream();
1726                 vars_of_device();
1727 #ifdef HAVE_DIALOGS
1728                 vars_of_dialog();
1729 #endif
1730                 vars_of_dired();
1731                 vars_of_doc();
1732 #ifdef HAVE_DRAGNDROP
1733                 vars_of_dragdrop();
1734 #endif
1735                 vars_of_editfns();
1736                 vars_of_elhash();
1737                 vars_of_emacs();
1738                 vars_of_eval();
1739
1740 #ifdef HAVE_X_WINDOWS
1741                 vars_of_event_Xt();
1742 #endif
1743 #if defined(HAVE_TTY) && (defined (DEBUG_TTY_EVENT_STREAM) || !defined (HAVE_X_WINDOWS))
1744                 vars_of_event_tty();
1745 #endif
1746                 vars_of_event_stream();
1747 #ifdef EF_USE_ASYNEQ
1748                 vars_of_workers();
1749                 vars_of_worker_asyneq();
1750 #endif
1751
1752                 vars_of_events();
1753                 vars_of_extents();
1754                 vars_of_faces();
1755                 vars_of_fileio();
1756 #ifdef CLASH_DETECTION
1757                 vars_of_filelock();
1758 #endif
1759                 vars_of_floatfns();
1760                 vars_of_font_lock();
1761                 vars_of_frame();
1762                 vars_of_glyphs();
1763                 vars_of_glyphs_eimage();
1764                 vars_of_glyphs_widget();
1765                 vars_of_gui();
1766                 vars_of_gutter();
1767                 vars_of_indent();
1768                 vars_of_insdel();
1769                 vars_of_intl();
1770 #ifdef HAVE_XIM
1771 #ifdef XIM_MOTIF
1772                 vars_of_input_method_motif();
1773 #else                           /* XIM_XLIB */
1774                 vars_of_input_method_xlib();
1775 #endif
1776 #endif                          /* HAVE_XIM */
1777                 vars_of_keymap();
1778                 vars_of_lread();
1779                 vars_of_lstream();
1780                 vars_of_macros();
1781                 vars_of_md5();
1782 #ifdef HAVE_DATABASE
1783                 vars_of_database();
1784 #endif
1785 #ifdef HAVE_MENUBARS
1786                 vars_of_menubar();
1787 #endif
1788                 vars_of_media();
1789                 vars_of_minibuf();
1790                 vars_of_dynacat();
1791 #if defined WITH_EMODULES && defined HAVE_EMODULES && 0
1792                 vars_of_module();
1793 #elif defined WITH_EMODULES && defined HAVE_EMODULES
1794                 vars_of_emodng();
1795 #endif
1796                 vars_of_objects();
1797                 vars_of_print();
1798
1799 #ifndef NO_SUBPROCESSES
1800                 vars_of_process();
1801 #ifdef HAVE_UNIX_PROCESSES
1802                 vars_of_process_unix();
1803 #endif
1804 #endif
1805
1806                 vars_of_profile();
1807 #if defined (HAVE_MMAP) && defined (REL_ALLOC) && !defined(DOUG_LEA_MALLOC)
1808                 vars_of_ralloc();
1809 #endif                          /* HAVE_MMAP && REL_ALLOC */
1810                 vars_of_redisplay();
1811 #ifdef HAVE_SCROLLBARS
1812                 vars_of_scrollbar();
1813 #endif
1814                 vars_of_search();
1815                 vars_of_select();
1816                 vars_of_sound();
1817                 vars_of_symbols();
1818                 vars_of_syntax();
1819 #ifdef HAVE_TOOLBARS
1820                 vars_of_toolbar();
1821 #endif
1822                 vars_of_undo();
1823                 vars_of_window();
1824
1825 #ifdef HAVE_TTY
1826                 vars_of_console_tty();
1827                 vars_of_frame_tty();
1828                 vars_of_objects_tty();
1829 #endif
1830
1831 #ifdef HAVE_X_WINDOWS
1832 #ifdef HAVE_BALLOON_HELP
1833                 vars_of_balloon_x();
1834 #endif
1835                 vars_of_device_x();
1836 #ifdef HAVE_DIALOGS
1837                 vars_of_dialog_x();
1838 #endif
1839                 vars_of_frame_x();
1840                 vars_of_glyphs_x();
1841 #ifdef HAVE_MENUBARS
1842                 vars_of_menubar_x();
1843 #endif
1844                 vars_of_objects_x();
1845                 vars_of_select_x();
1846 #ifdef HAVE_SCROLLBARS
1847                 vars_of_scrollbar_x();
1848 #endif
1849 #if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_DIALOGS) || defined (HAVE_TOOLBARS)
1850                 vars_of_gui_x();
1851 #endif
1852 #endif                          /* HAVE_X_WINDOWS */
1853
1854 #ifdef MULE
1855                 vars_of_mule();
1856                 vars_of_mule_ccl();
1857                 vars_of_mule_charset();
1858 #endif
1859 #ifdef FILE_CODING
1860                 vars_of_file_coding();
1861 #endif
1862 #ifdef MULE
1863 #ifdef HAVE_WNN
1864                 vars_of_mule_wnn();
1865 #endif
1866 #ifdef HAVE_CANNA
1867                 vars_of_mule_canna();
1868 #endif                          /* HAVE_CANNA */
1869 #endif                          /* MULE */
1870
1871 #ifdef SUNPRO
1872                 vars_of_sunpro();
1873 #endif
1874
1875 #ifdef HAVE_LDAP
1876                 vars_of_eldap();
1877 #endif
1878
1879 #ifdef HAVE_POSTGRESQL
1880                 vars_of_postgresql();
1881 #endif
1882
1883 #ifdef HAVE_OPENSSL
1884                 vars_of_openssl();
1885 #endif
1886
1887 #ifdef HAVE_GPM
1888                 vars_of_gpmevent();
1889 #endif
1890
1891 #ifdef WITH_NUMBER_TYPES
1892                 vars_of_ent();
1893 #endif
1894
1895 #ifdef HAVE_LIBFFI
1896                 vars_of_ffi();
1897 #endif
1898
1899                 vars_of_dllist();
1900                 vars_of_skiplist();
1901                 vars_of_bloom();
1902
1903                 /* Now initialize any specifier variables.  We do this later
1904                    because it has some dependence on the vars initialized
1905                    above.
1906
1907                    These functions should *only* initialize specifier variables,
1908                    and may make use of the following functions/macros in addition
1909                    to the ones listed above:
1910
1911                    DEFVAR_SPECIFIER()
1912                    Fmake_specifier()
1913                    set_specifier_fallback()
1914                    set_specifier_caching()
1915                  */
1916
1917                 specifier_vars_of_glyphs();
1918                 specifier_vars_of_glyphs_widget();
1919                 specifier_vars_of_gutter();
1920 #ifdef HAVE_MENUBARS
1921                 specifier_vars_of_menubar();
1922 #endif
1923                 specifier_vars_of_redisplay();
1924 #ifdef HAVE_SCROLLBARS
1925                 specifier_vars_of_scrollbar();
1926 #endif
1927 #ifdef HAVE_TOOLBARS
1928                 specifier_vars_of_toolbar();
1929 #endif
1930                 specifier_vars_of_window();
1931
1932                 /* Now comes all the rest of the variables that couldn't
1933                    be handled above.  There may be dependencies on variables
1934                    initialized above, and dependencies between one complex_vars_()
1935                    function and another. */
1936
1937                 /* Calls Fmake_range_table(). */
1938                 complex_vars_of_regex();
1939                 /* Calls Fmake_range_table(). */
1940                 complex_vars_of_search();
1941
1942                 /* Calls make_lisp_hash_table(). */
1943                 complex_vars_of_extents();
1944
1945                 /* Depends on hash tables and specifiers. */
1946                 complex_vars_of_faces();
1947
1948 #ifdef MULE
1949                 /* These two depend on hash tables and various variables declared
1950                    earlier.  The second may also depend on the first. */
1951                 complex_vars_of_mule_charset();
1952 #endif
1953 #ifdef FILE_CODING
1954                 complex_vars_of_file_coding();
1955 #endif
1956
1957                 /* This calls allocate_glyph(), which creates specifiers
1958                    and also relies on a variable (Vthe_nothing_vector) initialized
1959                    above.  It also calls make_ext_string(), which under Mule
1960                    could require that the charsets be initialized. */
1961                 complex_vars_of_glyphs();
1962
1963                 /* These rely on the glyphs just created in the previous function,
1964                    and call Fadd_spec_to_specifier(), which relies on various
1965                    variables initialized above. */
1966 #ifdef HAVE_X_WINDOWS
1967                 complex_vars_of_glyphs_x();
1968 #endif
1969
1970                 /* This calls Fmake_glyph_internal(). */
1971                 complex_vars_of_alloc();
1972
1973                 /* This calls Fmake_glyph_internal(). */
1974 #ifdef HAVE_MENUBARS
1975                 complex_vars_of_menubar();
1976 #endif
1977
1978                 /* This calls Fmake_glyph_internal(). */
1979 #ifdef HAVE_SCROLLBARS
1980                 complex_vars_of_scrollbar();
1981 #endif
1982
1983                 /* This calls allocate_glyph(). */
1984                 complex_vars_of_frame();
1985
1986                 /* This calls Fcopy_category_table() under Mule, which calls who
1987                    knows what. */
1988                 complex_vars_of_chartab();
1989
1990                 /* This calls set_string_char(), which (under Mule) depends on the
1991                    charsets being initialized. */
1992                 complex_vars_of_casetab();
1993
1994                 /* This calls Fcopy_syntax_table(), which relies on char tables. */
1995                 complex_vars_of_syntax();
1996
1997                 /* This initializes buffer-local variables, sets things up so
1998                    that buffers can be created, and creates a couple of basic
1999                    buffers.  This depends on Vstandard_syntax_table and
2000                    Vstandard_category_table (initialized in the previous
2001                    functions), as well as a whole horde of variables that may
2002                    have been initialized above. */
2003                 complex_vars_of_buffer();
2004
2005                 /* This initializes console-local variables. */
2006                 complex_vars_of_console();
2007
2008                 /* This creates a couple more buffers, and depends on the
2009                    previous function. */
2010                 complex_vars_of_minibuf();
2011
2012                 /* These two might call Ffile_name_as_directory(), which
2013                    might depend on all sorts of things; I'm not sure. */
2014                 complex_vars_of_emacs();
2015
2016                 /* This creates a couple of basic keymaps and depends on Lisp
2017                    hash tables and Ffset() (both of which depend on some variables
2018                    initialized in the vars_of_*() section) and possibly other
2019                    stuff. */
2020                 complex_vars_of_keymap();
2021
2022                 /* Calls make_lisp_hash_table() and creates a keymap */
2023                 complex_vars_of_event_stream();
2024
2025 #ifdef ERROR_CHECK_GC
2026                 {
2027                         extern int always_gc;
2028                         if (always_gc)  /* purification debugging hack */
2029                                 garbage_collect_1();
2030                 }
2031 #endif
2032 #ifdef PDUMP
2033         } else if (!restart) {  /* after successful pdump_load() */
2034                 reinit_alloc_once_early();
2035                 reinit_symbols_once_early();
2036                 reinit_opaque_once_early();
2037
2038                 reinit_console_type_create_stream();
2039 #ifdef HAVE_TTY
2040                 reinit_console_type_create_tty();
2041 #endif
2042 #ifdef HAVE_X_WINDOWS
2043                 reinit_console_type_create_x();
2044                 reinit_console_type_create_device_x();
2045 #endif
2046
2047                 reinit_specifier_type_create();
2048                 reinit_specifier_type_create_image();
2049                 reinit_specifier_type_create_gutter();
2050                 reinit_specifier_type_create_objects();
2051 #ifdef HAVE_TOOLBARS
2052                 reinit_specifier_type_create_toolbar();
2053 #endif
2054
2055                 structure_type_create();
2056
2057                 structure_type_create_chartab();
2058                 structure_type_create_faces();
2059                 structure_type_create_rangetab();
2060                 structure_type_create_hash_table();
2061
2062                 lstream_type_create();
2063 #ifdef FILE_CODING
2064                 lstream_type_create_file_coding();
2065 #endif
2066 #ifdef HAVE_UNIX_PROCESSES
2067                 process_type_create_unix();
2068 #endif
2069
2070                 reinit_vars_of_buffer();
2071                 reinit_vars_of_console();
2072 #ifdef DEBUG_SXEMACS
2073                 reinit_vars_of_debug();
2074 #endif
2075                 reinit_vars_of_device();
2076                 reinit_vars_of_eval();
2077 #ifdef HAVE_X_WINDOWS
2078                 reinit_vars_of_event_Xt();
2079 #endif
2080 #if defined(HAVE_TTY) && (defined (DEBUG_TTY_EVENT_STREAM) || !defined (HAVE_X_WINDOWS))
2081                 reinit_vars_of_event_tty();
2082 #endif
2083                 reinit_vars_of_event_stream();
2084 #ifdef EF_USE_ASYNEQ
2085                 reinit_vars_of_worker_asyneq();
2086 #endif
2087                 reinit_vars_of_events();
2088                 reinit_vars_of_extents();
2089                 reinit_vars_of_fileio();
2090                 reinit_vars_of_font_lock();
2091                 reinit_vars_of_glyphs();
2092                 reinit_vars_of_glyphs_widget();
2093                 reinit_vars_of_insdel();
2094                 reinit_vars_of_lread();
2095                 reinit_vars_of_lstream();
2096                 reinit_vars_of_minibuf();
2097                 reinit_vars_of_dynacat();
2098 #if defined WITH_EMODULES && defined HAVE_EMODULES && 0
2099                 reinit_vars_of_module();
2100 #elif defined WITH_EMODULES && defined HAVE_EMODULES
2101                 reinit_vars_of_emodng();
2102 #endif
2103                 reinit_vars_of_objects();
2104                 reinit_vars_of_print();
2105                 reinit_vars_of_search();
2106                 reinit_vars_of_undo();
2107                 reinit_vars_of_window();
2108
2109 #ifdef HAVE_X_WINDOWS
2110                 reinit_vars_of_device_x();
2111 #ifdef HAVE_SCROLLBARS
2112                 reinit_vars_of_scrollbar_x();
2113 #endif
2114 #ifdef HAVE_MENUBARS
2115                 reinit_vars_of_menubar_x();
2116 #endif
2117                 reinit_vars_of_select_x();
2118 #if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_DIALOGS) || defined (HAVE_TOOLBARS)
2119                 reinit_vars_of_gui_x();
2120 #endif
2121 #endif                          /* HAVE_X_WINDOWS */
2122
2123 #if defined(MULE) && defined(HAVE_WNN)
2124                 reinit_vars_of_mule_wnn();
2125 #endif
2126
2127                 reinit_complex_vars_of_buffer();
2128                 reinit_complex_vars_of_console();
2129                 reinit_complex_vars_of_minibuf();
2130
2131 #ifdef HAVE_LIBFFI
2132                 reinit_vars_of_ffi();
2133 #endif
2134
2135 #if defined USE_STATIC_ASE && USE_STATIC_ASE
2136                 reinit_vars_of_ase();
2137 #endif
2138
2139 #endif                          /* PDUMP */
2140         }
2141
2142         /* the category subsystem needs some inits */
2143         dllist_reinit();
2144         elhash_reinit();
2145         skiplist_reinit();
2146
2147         /* CONGRATULATIONS!!!  We have successfully initialized the Lisp
2148            engine. */
2149
2150         if (initialized) {
2151                 /* Stuff that should not be done at dump time, including stuff that
2152                    needs to be reset at run time.  Order below should not matter.
2153
2154                    Many initializations taken from the environment should go here. */
2155                 reinit_alloc();
2156                 reinit_eval();
2157 #ifdef MULE_REGEXP
2158                 reinit_mule_category();
2159 #endif
2160 #ifdef HAVE_POSTGRESQL
2161                 init_postgresql_from_environment();
2162 #endif
2163         }
2164
2165         /* Now do further initialization/setup of stuff that is not needed by the
2166            syms_of_() routines.  This involves stuff that only is enabled in
2167            an interactive run (redisplay, user input, etc.) and stuff that is
2168            not needed until we start loading Lisp code (the reader).  A lot
2169            of this stuff involves querying the current environment and needs
2170            to be done both at dump time and at run time. */
2171
2172         init_initial_directory();       /* get the directory to use for the
2173                                            "*scratch*" buffer, etc. */
2174
2175         init_callproc();        /* Set up the process environment (so that egetenv
2176                                    works), the basic directory variables
2177                                    (exec-directory and so on), and stuff
2178                                    related to subprocesses.  This should be
2179                                    first because many of the functions below
2180                                    call egetenv() to get environment variables. */
2181         init_lread();           /* Set up the Lisp reader. */
2182         init_cmdargs(argc, (Extbyte **) argv, skip_args);       /* Create list Vcommand_line_args */
2183         init_buffer();          /* Set default directory of *scratch* buffer */
2184
2185         init_redisplay();       /* Determine terminal type.
2186                                    init_sys_modes uses results */
2187         init_frame();
2188         init_event_stream();    /* Set up so we can get user input. */
2189         init_macros();          /* set up so we can run macros. */
2190         init_editfns();         /* Determine the name of the user we're running as */
2191         init_sxemacs_process(); /* set up for calling subprocesses */
2192
2193 #ifdef WITH_NUMBER_TYPES
2194         /* Set up bignums, ratios, bigfloats, complex numbers.
2195          * This must be done before the Lisp reader is set up.
2196          */
2197         init_ent ();
2198 #endif
2199
2200 #ifdef SUNPRO
2201         init_sunpro();          /* Set up Sunpro usage tracking */
2202 #endif
2203 #if defined (HAVE_NATIVE_SOUND) && defined (hp9000s800) && 0
2204         init_hpplay();
2205 #endif
2206 #ifdef HAVE_TTY
2207         init_device_tty();
2208 #endif
2209         init_console_stream(restart);   /* Create the first console */
2210
2211         /* try to get the actual pathname of the exec file we are running */
2212         if (!restart) {
2213                 Vinvocation_name = Fcar(Vcommand_line_args);
2214                 if (XSTRING_DATA(Vinvocation_name)[0] == '-') {
2215                         /* SXEmacs as a login shell, oh goody! */
2216                         Vinvocation_name = build_string(getenv("SHELL"));
2217                 }
2218                 Vinvocation_directory = Vinvocation_name;
2219
2220                 if (!NILP(Ffile_name_directory(Vinvocation_name))) {
2221                         /* invocation-name includes a directory component -- presumably it
2222                            is relative to cwd, not $PATH */
2223                         Vinvocation_directory =
2224                             Fexpand_file_name(Vinvocation_name, Qnil);
2225                         Vinvocation_path = Qnil;
2226                 } else {
2227                         Vinvocation_path = decode_env_path("PATH", NULL);
2228                         locate_file(Vinvocation_path, Vinvocation_name,
2229                                     Vlisp_EXEC_SUFFIXES,
2230                                     &Vinvocation_directory, X_OK);
2231                 }
2232
2233                 if (NILP(Vinvocation_directory))
2234                         Vinvocation_directory = Vinvocation_name;
2235
2236                 /* kick double /s as we want a standard posix name */
2237                 for (unsigned char *p = XSTRING_DATA(Vinvocation_name),
2238                              *q = p; ((*q = *p));) {
2239                         if (*q++ == '/') {
2240                                 while (*++p == '/');
2241                         } else {
2242                                 p++;
2243                         }
2244                 }
2245
2246                 Vinvocation_name =
2247                     Ffile_name_nondirectory(Vinvocation_directory);
2248                 Vinvocation_directory =
2249                     Ffile_name_directory(Vinvocation_directory);
2250         }
2251
2252 #if defined (LOCALTIME_CACHE) && defined (HAVE_TZSET)
2253         /* sun's localtime() has a bug.  it caches the value of the time
2254            zone rather than looking it up every time.  Since localtime() is
2255            called to bolt the undumping time into the undumped emacs, this
2256            results in localtime() ignoring the TZ environment variable.
2257            This flushes the new TZ value into localtime(). */
2258         tzset();
2259 #endif                          /* LOCALTIME_CACHE and TZSET */
2260
2261         load_me = Qnil;
2262         if (!initialized) {
2263                 /* Handle -l loadup-and-dump, args passed by Makefile. */
2264                 if (argc > 2 + skip_args && !strcmp(argv[1 + skip_args], "-l"))
2265                         load_me = build_string(argv[2 + skip_args]);
2266 #if 0
2267                 /* CANNOT_DUMP - this can never be right in SXEmacs --andyp */
2268                 /* Unless next switch is -nl, load "loadup.el" first thing.  */
2269                 if (!
2270                     (argc > 1 + skip_args
2271                      && !strcmp(argv[1 + skip_args], "-nl")))
2272                         load_me = build_string("loadup.el");
2273 #endif                          /* CANNOT_DUMP */
2274         }
2275 #ifdef QUANTIFY
2276         if (initialized)
2277                 quantify_start_recording_data();
2278 #endif                          /* QUANTIFY */
2279
2280         initialized = 1;
2281         inhibit_non_essential_printing_operations = 0;
2282
2283         /* This never returns.  */
2284         initial_command_loop(load_me);
2285         /* NOTREACHED */
2286 }
2287 \f
2288 /* Sort the args so we can find the most important ones
2289    at the beginning of argv.  */
2290
2291 /* First, here's a table of all the standard options.  */
2292
2293 struct standard_args {
2294         const char *name;
2295         const char *longname;
2296         int priority;
2297         int nargs;
2298 };
2299
2300 static const struct standard_args standard_args[] = {
2301         /* Handled by main_1 above: */
2302         {"--make-docfile", 0, 105, 0},
2303         {"-sd", "--show-dump-id", 105, 0},
2304         {"-t", "--terminal", 100, 1},
2305         {"-nd", "--no-dump-file", 95, 0},
2306         {"-ct", "--color-terminal", 92, 0},
2307         {"-nw", "--no-windows", 90, 0},
2308         {"-batch", "--batch", 85, 0},
2309         {"-debug-paths", "--debug-paths", 82, 0},
2310         {"-help", "--help", 80, 0},
2311         {"-version", "--version", 75, 0},
2312         {"-V", 0, 75, 0},
2313         {"-d", "--display", 80, 1},
2314         {"-display", 0, 80, 1},
2315         {"-NXHost", 0, 79, 0},
2316         {"-MachLaunch", 0, 79, 0},
2317
2318         /* Handled by command-line-early in startup.el: */
2319         {"-q", "--no-init-file", 50, 0},
2320         {"-unmapped", 0, 50, 0},
2321         {"-no-init-file", 0, 50, 0},
2322         {"-vanilla", "--vanilla", 50, 0},
2323         {"-no-autoloads", "--no-autoloads", 50, 0},
2324         {"-no-site-file", "--no-site-file", 40, 0},
2325         {"-no-early-packages", "--no-early-packages", 35, 0},
2326         {"-u", "--user", 30, 1},
2327         {"-user", 0, 30, 1},
2328         {"-debug-init", "--debug-init", 20, 0},
2329         {"-debug-paths", "--debug-paths", 20, 0},
2330
2331         /* Xt options: */
2332         {"-i", "--icon-type", 15, 0},
2333         {"-itype", 0, 15, 0},
2334         {"-iconic", "--iconic", 15, 0},
2335         {"-bg", "--background-color", 10, 1},
2336         {"-background", 0, 10, 1},
2337         {"-fg", "--foreground-color", 10, 1},
2338         {"-foreground", 0, 10, 1},
2339         {"-bd", "--border-color", 10, 1},
2340         {"-bw", "--border-width", 10, 1},
2341         {"-ib", "--internal-border", 10, 1},
2342         {"-ms", "--mouse-color", 10, 1},
2343         {"-cr", "--cursor-color", 10, 1},
2344         {"-fn", "--font", 10, 1},
2345         {"-font", 0, 10, 1},
2346         {"-g", "--geometry", 10, 1},
2347         {"-geometry", 0, 10, 1},
2348         {"-T", "--title", 10, 1},
2349         {"-title", 0, 10, 1},
2350         {"-name", "--name", 10, 1},
2351         {"-xrm", "--xrm", 10, 1},
2352         {"-r", "--reverse-video", 5, 0},
2353         {"-rv", 0, 5, 0},
2354         {"-reverse", 0, 5, 0},
2355         {"-hb", "--horizontal-scroll-bars", 5, 0},
2356         {"-vb", "--vertical-scroll-bars", 5, 0},
2357
2358         /* These have the same priority as ordinary file name args,
2359            so they are not reordered with respect to those.  */
2360         {"-L", "--directory", 0, 1},
2361         {"-directory", 0, 0, 1},
2362         {"-l", "--load", 0, 1},
2363         {"-load", 0, 0, 1},
2364         {"-f", "--funcall", 0, 1},
2365         {"-funcall", 0, 0, 1},
2366         {"-eval", "--eval", 0, 1},
2367         {"-insert", "--insert", 0, 1},
2368         /* This should be processed after ordinary file name args and the like.  */
2369         {"-kill", "--kill", -10, 0},
2370 };
2371
2372 /* Reorder the elements of ARGV (assumed to have ARGC elements)
2373    so that the highest priority ones come first.
2374    Do not change the order of elements of equal priority.
2375    If an option takes an argument, keep it and its argument together.  */
2376
2377 static void sort_args(int argc, char **argv)
2378 {
2379         char **new_argv = (char**)malloc(sizeof(char*) * argc);
2380         /* For each element of argv,
2381            the corresponding element of options is:
2382            0 for an option that takes no arguments,
2383            1 for an option that takes one argument, etc.
2384            -1 for an ordinary non-option argument.  */
2385         int *options = (int*)malloc(sizeof(int) * argc);
2386         int *priority = (int*)malloc(sizeof(int) * argc);
2387         int to = 1;
2388         int from;
2389         int i;
2390         int end_of_options_p = 0;
2391
2392         /* Categorize all the options,
2393            and figure out which argv elts are option arguments.  */
2394         for (from = 1; from < argc; from++) {
2395                 options[from] = -1;
2396                 priority[from] = 0;
2397                 /* Pseudo options "--" and "run-temacs" indicate end of
2398                    options */
2399                 if (!strcmp(argv[from], "--") ||
2400                     !strcmp(argv[from], "run-temacs"))
2401                         end_of_options_p = 1;
2402                 if (!end_of_options_p && argv[from][0] == '-') {
2403                         int match, thislen;
2404                         char *equals;
2405
2406                         /* Look for a match with a known old-fashioned
2407                            option.  */
2408                         for (i = 0; i < countof(standard_args); i++) {
2409                                 if (!strcmp(argv[from],
2410                                             standard_args[i].name)) {
2411                                         options[from] = standard_args[i].nargs;
2412                                         priority[from] =
2413                                             standard_args[i].priority;
2414                                         if (from + standard_args[i].nargs >=
2415                                             argc) {
2416                                                 fatal("Option `%s' requires "
2417                                                       "an argument\n",
2418                                                       argv[from]);
2419                                         }
2420                                         from += standard_args[i].nargs;
2421                                         goto done;
2422                                 }
2423                         }
2424
2425                         /* Look for a match with a known long option.  MATCH is
2426                            -1 if no match so far, -2 if two or more matches so
2427                            far,
2428                            >= 0 (the table index of the match) if just one match
2429                            >so far.  */
2430                         if (argv[from][1] == '-') {
2431                                 match = -1;
2432                                 thislen = strlen(argv[from]);
2433                                 equals = strchr(argv[from], '=');
2434                                 if (equals != 0)
2435                                         thislen = equals - argv[from];
2436
2437                                 for (i = 0; i < countof(standard_args); i++)
2438                                         if (standard_args[i].longname
2439                                             && !strncmp(argv[from],
2440                                                         standard_args[i].
2441                                                         longname, thislen)) {
2442                                                 if (match == -1)
2443                                                         match = i;
2444                                                 else
2445                                                         match = -2;
2446                                         }
2447
2448                                 /* If we found exactly one match, use that.  */
2449                                 if (match >= 0) {
2450                                         options[from] =
2451                                                 standard_args[match].nargs;
2452                                         priority[from] =
2453                                                 standard_args[match].priority;
2454                                         /* If --OPTION=VALUE syntax is used,
2455                                            this option uses just one argv
2456                                            element.  */
2457                                         if (equals != 0)
2458                                                 options[from] = 0;
2459                                         if (from + options[from] >= argc) {
2460                                                 fatal("Option `%s' requires "
2461                                                       "an argument\n",
2462                                                       argv[from]);
2463                                         }
2464                                         from += options[from];
2465                                 }
2466                         }
2467                 done:
2468                         ;
2469                 }
2470         }
2471
2472         /* Copy the arguments, in order of decreasing priority, to NEW_ARGV.  */
2473         new_argv[0] = argv[0];
2474         while (to < argc) {
2475                 int best = -1;
2476                 int best_priority = -9999;
2477
2478                 /* Find the highest priority remaining option.
2479                    If several have equal priority, take the first of them.  */
2480                 for (from = 1; from < argc; from++) {
2481                         if (argv[from] != 0 && priority[from] > best_priority) {
2482                                 best_priority = priority[from];
2483                                 best = from;
2484                         }
2485                         /* Skip option arguments--they are tied to the options.  */
2486                         if (options[from] > 0) {
2487                                 from += options[from];
2488                         }
2489                 }
2490
2491                 if (best < 0) {
2492                         abort();
2493                 }
2494
2495                 /* Copy the highest priority remaining option, with its args, to
2496                    NEW_ARGV.  */
2497                 new_argv[to++] = argv[best];
2498                 for (i = 0; i < options[best]; i++) {
2499                         new_argv[to++] = argv[best + i + 1];
2500                 }
2501                 /* Clear out this option in ARGV.  */
2502                 argv[best] = 0;
2503                 for (i = 0; i < options[best]; i++) {
2504                         argv[best + i + 1] = 0;
2505                 }
2506         }
2507
2508         memcpy(argv, new_argv, sizeof(char *) * argc);
2509         free(new_argv);
2510         free(options);
2511         free(priority);
2512         return;
2513 }
2514
2515 DEFUN("running-temacs-p", Frunning_temacs_p, 0, 0, 0, /*
2516 True if running temacs.  This means we are in the dumping stage.
2517 This is false during normal execution of the `sxemacs' program, and
2518 becomes false once `run-emacs-from-temacs' is run.
2519 */
2520       ())
2521 {
2522         return run_temacs_argc >= 0 ? Qt : Qnil;
2523 }
2524
2525 DEFUN("run-emacs-from-temacs", Frun_emacs_from_temacs, 0, MANY, 0, /*
2526 Do not call this.  It will reinitialize your SXEmacs.  You'll be sorry.
2527 */
2528 /* If this function is called from startup.el, it will be possible to run
2529    temacs as an editor using 'temacs -batch -l loadup.el run-temacs', instead
2530    of having to dump an emacs and then run that (when debugging emacs itself,
2531    this can be much faster)). [Actually, the speed difference isn't that
2532    much as long as your filesystem is local, and you don't end up with
2533    a dumped version in case you want to rerun it.  This function is most
2534    useful when used as part of the `make all-elc' command. --ben]
2535    This will "restart" emacs with the specified command-line arguments.
2536
2537    Martin thinks this function is most useful when using debugging
2538    tools like Purify or tcov that get confused by SXEmacs' dumping.  */
2539       (int nargs, Lisp_Object * args))
2540 {
2541         int ac;
2542         const Extbyte *wampum = NULL;
2543         int namesize;
2544         int total_len;
2545         Lisp_Object orig_invoc_name = Fcar(Vcommand_line_args);
2546         const Extbyte **wampum_all = alloca_array(const Extbyte *, nargs);
2547         int *wampum_all_len = alloca_array(int, nargs);
2548
2549         assert(!gc_in_progress);
2550
2551         if (run_temacs_argc < 0)
2552                 error("I've lost my temacs-hood.");
2553
2554         /* Need to convert the orig_invoc_name and all of the arguments
2555            to external format. */
2556
2557         TO_EXTERNAL_FORMAT(LISP_STRING, orig_invoc_name,
2558                            ALLOCA, (wampum, namesize), Qnative);
2559         if ( wampum == NULL )
2560                 error("Could not transcode invocation name");
2561
2562         namesize++;
2563
2564         for (ac = 0, total_len = namesize; ac < nargs; ac++) {
2565                 CHECK_STRING(args[ac]);
2566                 wampum_all[ac]=NULL;
2567                 TO_EXTERNAL_FORMAT(LISP_STRING, args[ac],
2568                                    ALLOCA, (wampum_all[ac], wampum_all_len[ac]),
2569                                    Qnative);
2570                 if(wampum_all[ac]==NULL) {
2571                         error("Could not transcode arguments");
2572                 }
2573                 wampum_all_len[ac]++;
2574                 total_len += wampum_all_len[ac];
2575         }
2576         DO_REALLOC(run_temacs_args, run_temacs_args_size, total_len, char);
2577         DO_REALLOC(run_temacs_argv, run_temacs_argv_size, nargs + 2, char *);
2578
2579         memcpy(run_temacs_args, wampum, namesize);
2580         run_temacs_argv[0] = run_temacs_args;
2581         for (ac = 0; ac < nargs; ac++) {
2582                 memcpy(run_temacs_args + namesize,
2583                        wampum_all[ac], wampum_all_len[ac]);
2584                 run_temacs_argv[ac + 1] = run_temacs_args + namesize;
2585                 namesize += wampum_all_len[ac];
2586         }
2587         run_temacs_argv[nargs + 1] = 0;
2588         catchlist = NULL;       /* Important!  Otherwise free_cons() calls in
2589                                    condition_case_unwind() may lead to GC death. */
2590         unbind_to(0, Qnil);     /* this closes loadup.el */
2591         purify_flag = 0;
2592         run_temacs_argc = nargs + 1;
2593         LONGJMP(run_temacs_catch, 1);
2594         return Qnil;            /* not reached; warning suppression */
2595 }
2596
2597 /* defined in alloc.c */
2598 extern void init_bdwgc(void);
2599
2600 /* ARGSUSED */
2601 int
2602 main(int argc, char **argv, char **envp)
2603 {
2604         int volatile vol_argc = argc;
2605         char **volatile vol_argv = argv;
2606         char **volatile vol_envp = envp;
2607         /* This is hairy.  We need to compute where the SXEmacs binary
2608            was invoked from because temacs initialization requires it
2609            to find the lisp directories.  The code that recomputes the
2610            path is guarded by the restarted flag.  There are three
2611            possible paths I've found so far through this:
2612
2613            temacs -- When running temacs for basic build stuff, the
2614            first main_1 will be the only one invoked.  It must compute
2615            the path else there will be a very ugly bomb in startup.el
2616            (can't find obvious location for doc-directory
2617            data-directory, etc.).
2618
2619            temacs w/ run-temacs on the command line -- This is run to
2620            bytecompile all the out of date dumped lisp.  It will
2621            execute both of the main_1 calls and the second one must
2622            not touch the first computation because argc/argv are hosed
2623            the second time through.
2624
2625            sxemacs -- Only the second main_1 is executed.  The
2626            invocation path must computed but this only matters when
2627            running in place or when running as a login shell.
2628
2629            As a bonus for straightening this out, SXEmacs can now be
2630            run in place as a login shell.  This never used to work.
2631
2632            As another bonus, we can now guarantee that (concat
2633            invocation-directory invocation-name) contains the filename
2634            of the SXEmacs binary we are running.  This can now be used
2635            in a definite test for out of date dumped files.  -slb 
2636         */
2637
2638         int restarted = 0;
2639
2640         int arg;
2641         assert(vol_argv[0] != NULL || vol_argv[0][0] != '\0');
2642         assert(argc >= 1);
2643         for( arg=1; arg < argc; arg++ ) {
2644                 assert(vol_argv[arg] != NULL);
2645         }
2646         assert(vol_argv[argc] == NULL);
2647
2648 #ifdef QUANTIFY
2649         quantify_stop_recording_data();
2650         quantify_clear_data();
2651 #endif /* QUANTIFY */
2652
2653         inhibit_non_essential_printing_operations = 1;
2654         suppress_early_error_handler_backtrace = 0;
2655         lim_data = 0;   /* force reinitialization of this variable */
2656
2657         /* Lisp_Object must fit in a word; check VALBITS and GCTYPEBITS */
2658         assert(sizeof(Lisp_Object) == sizeof(void *));
2659
2660 #ifdef LINUX_SBRK_BUG
2661         sbrk(1);
2662 #endif
2663
2664         /* defined in alloc.c */
2665         init_bdwgc();
2666
2667         if (!initialized) {
2668 #ifdef DOUG_LEA_MALLOC
2669                 if (mallopt(M_MMAP_MAX, 0) != 1)
2670                         abort();
2671 #endif
2672                 run_temacs_argc = 0;
2673                 if (!SETJMP(run_temacs_catch)) {
2674                         main_1(vol_argc, vol_argv, vol_envp, 0);
2675                 }
2676                 /* run-emacs-from-temacs called */
2677                 restarted = 1;
2678                 vol_argc = run_temacs_argc;
2679                 vol_argv = run_temacs_argv;
2680 #ifdef _SCO_DS
2681                 /* This makes absolutely no sense to anyone involved.  There are
2682                    several people using this stuff.  We've compared versions on
2683                    everything we can think of.  We can find no difference.
2684                    However, on both my systems environ is a plain old global
2685                    variable initialized to zero.  _environ is the one that
2686                    contains pointers to the actual environment.
2687
2688                    Since we can't figure out the difference (and we're hours
2689                    away from a release), this takes a very cowardly approach and
2690                    is bracketed with both a system specific preprocessor test
2691                    and a runtime "do you have this problem" test
2692
2693                    06/20/96 robertl@dgii.com */
2694                 {
2695                         extern char **_environ;
2696                         if ((unsigned)environ == 0)
2697                                 environ = _environ;
2698                 }
2699 #endif                          /* _SCO_DS */
2700                 vol_envp = environ;
2701         }
2702 #if defined (RUN_TIME_REMAP) && ! defined (PDUMP)
2703         else
2704                 /* obviously no-one uses this because where it was before initialized was
2705                  *always* true */
2706                 run_time_remap(argv[0]);
2707 #endif
2708
2709 #ifdef DOUG_LEA_MALLOC
2710         if (initialized && (malloc_state_ptr != NULL)) {
2711                 int rc = malloc_set_state(malloc_state_ptr);
2712                 if (rc != 0) {
2713                         stderr_out("malloc_set_state failed, rc = %d\n",
2714                                    rc);
2715                         abort();
2716                 }
2717 #if 0
2718                 free(malloc_state_ptr);
2719 #endif
2720                 /* mmap works in glibc-2.1, glibc-2.0 (Non-Mule only)
2721                  * and Linux libc5 */
2722 #if (defined(__GLIBC__) && __GLIBC_MINOR__ >= 1) ||                     \
2723         defined(_NO_MALLOC_WARNING_) ||                                 \
2724         (defined(__GLIBC__) && __GLIBC_MINOR__ < 1 && !defined(MULE)) || \
2725         defined(DEBUG_DOUG_LEA_MALLOC)
2726                 if (mallopt(M_MMAP_MAX, 0) != 1)
2727                         abort();
2728 #endif
2729 #ifdef REL_ALLOC
2730                 r_alloc_reinit();
2731 #endif
2732         }
2733  #endif                         /* DOUG_LEA_MALLOC */
2734
2735         run_temacs_argc = -1;
2736
2737         main_1(vol_argc, vol_argv, vol_envp, restarted);
2738
2739         return 0;               /* unreached */
2740 }
2741
2742 \f
2743 /* Dumping apparently isn't supported by versions of GCC >= 2.8. */
2744 /* The following needs conditionalization on whether either SXEmacs or */
2745 /* various system shared libraries have been built and linked with */
2746 /* GCC >= 2.8.  -slb */
2747 #if defined(GNU_MALLOC)
2748 static void voodoo_free_hook(void *mem)
2749 {
2750         /* Disable all calls to free() when SXEmacs is exiting and it doesn't */
2751         /* matter. */
2752         __free_hook =
2753 #if defined __GNUC__ || defined __INTEL_COMPILER
2754 /* prototype of __free_hook varies with glibc version */
2755             (__typeof__(__free_hook))
2756 #endif
2757             voodoo_free_hook;
2758 }
2759 #endif                          /* GNU_MALLOC */
2760
2761 DEFUN("kill-emacs", Fkill_emacs, 0, 1, "P", /*
2762 Exit the SXEmacs job and kill it.  Ask for confirmation, without argument.
2763 If ARG is an integer, return ARG as the exit program code.
2764 If ARG is a string, stuff it as keyboard input.
2765
2766 The value of `kill-emacs-hook', if not void,
2767 is a list of functions (of no args),
2768 all of which are called before SXEmacs is actually killed.
2769 */
2770       (arg))
2771 {
2772         /* This function can GC */
2773         struct gcpro gcpro1;
2774
2775         GCPRO1(arg);
2776
2777         if (feof(stdin))
2778                 arg = Qt;
2779
2780         if (!preparing_for_armageddon && !noninteractive)
2781                 run_hook(Qkill_emacs_hook);
2782
2783         ensure_no_quitting_from_now_on();
2784
2785         if (!preparing_for_armageddon) {
2786                 Lisp_Object concons, nextcons;
2787
2788                 /* Normally, go ahead and delete all the consoles now.
2789                    Some unmentionably lame window systems (MS Wwwww...... eek,
2790                    I can't even say it) don't properly clean up after themselves,
2791                    and even for those that do, it might be cleaner this way.
2792                    If we're going down, however, we don't do this (might
2793                    be too dangerous), and if we get a crash somewhere within
2794                    this loop, we'll still autosave and won't try this again. */
2795
2796                 LIST_LOOP_DELETING(concons, nextcons, Vconsole_list) {
2797                         /* There is very little point in deleting the stream console.
2798                            It uses stdio, which should flush any buffered output and
2799                            something can only go wrong. -slb */
2800                         /* I changed my mind.  There's a stupid hack in close to add
2801                            a trailing newline. */
2802                         /*if (!CONSOLE_STREAM_P (XCONSOLE (XCAR (concons)))) */
2803                         delete_console_internal(XCONSOLE(XCAR(concons)), 1, 1,
2804                                                 0);
2805                 }
2806         }
2807
2808         UNGCPRO;
2809
2810         shut_down_emacs(0, STRINGP(arg) ? arg : Qnil, 0);
2811
2812 #if defined(GNU_MALLOC)
2813         __free_hook =
2814 #if defined __GNUC__ || defined __INTEL_COMPILER
2815 /* prototype of __free_hook varies with glibc version */
2816             (__typeof__(__free_hook))
2817 #endif
2818             voodoo_free_hook;
2819 #endif
2820
2821         exit(INTP(arg) ? XINT(arg) : 0);
2822         /* NOTREACHED */
2823         return Qnil;            /* I'm sick of the compiler warning */
2824 }
2825
2826 /* Perform an orderly shutdown of SXEmacs.  Autosave any modified
2827    buffers, kill any child processes, clean up the terminal modes (if
2828    we're in the foreground), and other stuff like that.  Don't perform
2829    any redisplay; this may be called when SXEmacs is shutting down in
2830    the background, or after its X connection has died.
2831
2832    If SIG is a signal number, print a message for it.
2833
2834    This is called by fatal signal handlers and Fkill_emacs.  It used to
2835    be called by X protocol error handlers, but instead they now call
2836    Fkill_emacs. */
2837 static void shut_down_emacs(int sig, Lisp_Object stuff, int no_auto_save)
2838 {
2839         /* This function can GC */
2840         /* Prevent running of hooks and other non-essential stuff
2841            from now on.  */
2842         preparing_for_armageddon = 1;
2843
2844         ensure_no_quitting_from_now_on();
2845
2846 #ifdef QUANTIFY
2847         quantify_stop_recording_data();
2848 #endif                          /* QUANTIFY */
2849
2850         /* This is absolutely the most important thing to do, so make sure
2851            we do it now, before anything else.  We might have crashed and
2852            be in a weird inconsistent state, and potentially anything could
2853            set off another protection fault and cause us to bail out
2854            immediately. */
2855         /* Steve writes the following:
2856
2857            [[I'm not removing the code entirely, yet.  We have run up against
2858            a spate of problems in diagnosing crashes due to crashes within
2859            crashes.  It has very definitely been determined that code called
2860            during auto-saving cannot work if SXEmacs crashed inside of GC.
2861            We already auto-save on an itimer so there cannot be too much
2862            unsaved stuff around, and if we get better crash reports we might
2863            be able to get more problems fixed so I'm disabling this.  -slb]]
2864
2865            and DISABLES AUTO-SAVING ENTIRELY during crashes!  Way way bad idea.
2866
2867            Instead let's just be more intelligent about avoiding crashing
2868            when possible, esp. nested crashes.
2869          */
2870         if (!no_auto_save)
2871                 Fdo_auto_save(Qt, Qnil);        /* do this before anything hazardous */
2872
2873         fflush(stdout);
2874         reset_all_consoles();
2875         if (sig && sig != SIGTERM) {
2876                 if (sig == -1)
2877                         stderr_out("\nFatal error.\n\n");
2878                 else
2879                         stderr_out("\nFatal error (%d).\n\n", sig);
2880                 stderr_out
2881                     ("Your files have been auto-saved.\n"
2882                      "Use `M-x recover-session' to recover them.\n"
2883                      "\n"
2884                      "Your version of SXEmacs was distributed with a PROBLEMS file that  may describe\n"
2885                      "your crash, and with luck a workaround.  Please check it first, but do report\n"
2886                      "the crash anyway.  "
2887 #ifdef INFODOCK
2888                      "\n\nPlease report this bug by selecting `Report-Bug' in the InfoDock menu.\n"
2889                      "*BE SURE* to include the SXEmacs configuration from M-x describe-installation,\n"
2890                      "or the file Installation in the top directory of the build tree.\n"
2891 #else
2892                      "Please report this bug by invoking M-x report-sxemacs-bug,\n"
2893                      "or by selecting `Send Bug Report' from the Help menu.  If necessary, send\n"
2894                      "ordinary email to `sxemacs-devel@sxemacs.org'.  *MAKE SURE* to include the SXEmacs\n"
2895                      "configuration from M-x describe-installation, or equivalently the file\n"
2896                      "Installation in the top of the build tree.\n"
2897 #endif
2898 #ifndef _MSC_VER
2899                      "\n"
2900                      "*Please* try *hard* to obtain a C stack backtrace; without it, we are unlikely\n"
2901                      "to be able to analyze the problem.  Locate the core file produced as a result\n"
2902                      "of this crash (often called `core' or `core.<process-id>', and located in\n"
2903                      "the directory in which you started SXEmacs or your home directory), and type\n"
2904                      "\n" "  gdb "
2905 #endif
2906                     );
2907                 {
2908                         const char *name;
2909                         char *dir = 0;
2910
2911                         /* Now try to determine the actual path to the executable,
2912                            to try to make the backtrace-determination process as foolproof
2913                            as possible. */
2914                         if (STRINGP(Vinvocation_name))
2915                                 name = (char *)XSTRING_DATA(Vinvocation_name);
2916                         else
2917                                 name = "sxemacs";
2918                         if (STRINGP(Vinvocation_directory))
2919                                 dir =
2920                                     (char *)XSTRING_DATA(Vinvocation_directory);
2921                         if (!dir || dir[0] != '/')
2922                                 stderr_out("`which %s`", name);
2923                         else if (dir[strlen(dir) - 1] != '/')
2924                                 stderr_out("%s/%s", dir, name);
2925                         else
2926                                 stderr_out("%s%s", dir, name);
2927                 }
2928                 stderr_out
2929                     (" core\n"
2930                      "\n"
2931                      "then type `where' at the debugger prompt.  "
2932                      "No GDB on your system?  You may\n"
2933                      "have DBX, or XDB, or SDB.  (Ask your system "
2934                      "administrator if you need help.)\n"
2935                      "If no core file was produced, enable them "
2936                      "(often with `ulimit -c unlimited'\n"
2937                      "in case of future recurrance of the crash.\n");
2938         }
2939
2940         stuff_buffered_input(stuff);
2941
2942         kill_buffer_processes(Qnil);
2943
2944 #ifdef CLASH_DETECTION
2945         unlock_all_files();
2946 #endif
2947
2948 }
2949 \f
2950 #ifndef CANNOT_DUMP
2951
2952 #if !defined(PDUMP) || !defined(SYSTEM_MALLOC)
2953 extern char my_edata[];
2954 #endif
2955
2956 extern void disable_free_hook(void);
2957
2958 DEFUN("dump-emacs", Fdump_emacs, 2, 2, 0, /*
2959 Dump current state of SXEmacs into executable file FILENAME.
2960 Take symbols from SYMFILE (presumably the file you executed to run SXEmacs).
2961 This is used in the file `loadup.el' when building SXEmacs.
2962
2963 Remember to set `command-line-processed' to nil before dumping
2964 if you want the dumped SXEmacs to process its command line
2965 and announce itself normally when it is run.
2966 */
2967       (symfile, filename))
2968 {
2969         /* This function can GC */
2970         struct gcpro gcpro1, gcpro2;
2971         int opurify;
2972
2973         GCPRO2(filename, symfile);
2974
2975 #if 0
2976         /* kick them */
2977         Vinvocation_directory = Vinvocation_name = Qnil;
2978         Vcommand_line_args = Qnil;
2979 #endif
2980
2981 #ifdef FREE_CHECKING
2982         Freally_free(Qnil);
2983
2984         /* When we're dumping, we can't use the debugging free() */
2985         disable_free_hook();
2986 #endif
2987
2988         CHECK_STRING(filename);
2989         filename = Fexpand_file_name(filename, Qnil);
2990         if (!NILP(symfile)) {
2991                 CHECK_STRING(symfile);
2992                 if (XSTRING_LENGTH(symfile) > 0) {
2993                         symfile = Fexpand_file_name(symfile, Qnil);
2994                 } else {
2995                         symfile = Qnil;
2996                 }
2997         }
2998
2999         opurify = purify_flag;
3000         purify_flag = 0;
3001
3002         clear_message();
3003
3004         fflush(stderr);
3005         fflush(stdout);
3006
3007         disksave_object_finalization();
3008         release_breathing_space();
3009
3010         /* Tell malloc where start of impure now is */
3011         /* Also arrange for warnings when nearly out of space.  */
3012 #ifndef SYSTEM_MALLOC
3013         memory_warnings(my_edata, malloc_warning);
3014 #endif
3015
3016         UNGCPRO;
3017
3018         {
3019                 char *filename_ext;
3020                 char *symfile_ext;
3021
3022                 LISP_STRING_TO_EXTERNAL(filename, filename_ext, Qfile_name);
3023
3024                 if (STRINGP(symfile)) {
3025                         LISP_STRING_TO_EXTERNAL(symfile, symfile_ext,
3026                                                 Qfile_name);
3027                 } else {
3028                         symfile_ext = 0;
3029                 }
3030
3031                 garbage_collect_1();
3032
3033 #ifdef PDUMP
3034                 pdump(filename_ext);
3035 #else
3036
3037 #ifdef DOUG_LEA_MALLOC
3038                 malloc_state_ptr = malloc_get_state();
3039 #endif
3040                 /* here we break our rule that the filename conversion should
3041                    be performed at the actual time that the system call is made.
3042                    It's a whole lot easier to do the conversion here than to
3043                    modify all the unexec routines to ensure that filename
3044                    conversion is applied everywhere.  Don't worry about memory
3045                    leakage because this call only happens once. */
3046                 unexec(filename_ext, symfile_ext, (uintptr_t) my_edata, 0, 0);
3047 #ifdef DOUG_LEA_MALLOC
3048                 free(malloc_state_ptr);
3049 #endif
3050 #endif                          /* not PDUMP */
3051         }
3052
3053         purify_flag = opurify;
3054
3055         return Qnil;
3056 }
3057
3058 #endif                          /* not CANNOT_DUMP */
3059 \f
3060 /* Split STRING into a list of substrings.  The substrings are the
3061    parts of original STRING separated by SEPCHAR.  */
3062 static Lisp_Object
3063 split_string_by_emchar_1(const Bufbyte * string, Bytecount size, Emchar sepchar)
3064 {
3065         Lisp_Object result = Qnil;
3066         const Bufbyte *end = string + size;
3067
3068         while (1) {
3069                 const Bufbyte *p = string;
3070                 while (p < end) {
3071                         if (charptr_emchar(p) == sepchar)
3072                                 break;
3073                         INC_CHARPTR(p);
3074                 }
3075                 result = Fcons(make_string(string, p - string), result);
3076                 if (p < end) {
3077                         string = p;
3078                         INC_CHARPTR(string);    /* skip sepchar */
3079                 } else
3080                         break;
3081         }
3082         return Fnreverse(result);
3083 }
3084
3085 /* The same as the above, except PATH is an external C string (it is
3086    converted using Qfile_name), and sepchar is hardcoded to SEPCHAR
3087    (':' or whatever).  */
3088 Lisp_Object decode_path(/*const*/ char *path)
3089 {
3090         Bytecount newlen = 0;
3091         Bufbyte *newpath = NULL;
3092         if (!path)
3093                 return Qnil;
3094
3095         TO_INTERNAL_FORMAT(C_STRING, path, ALLOCA, (newpath, newlen),
3096                            Qfile_name);
3097
3098         /* #### Does this make sense?  It certainly does for
3099            decode_env_path(), but it looks dubious here.  Does any code
3100            depend on decode_path("") returning nil instead of an empty
3101            string?  */
3102         if (!newlen || !newpath)
3103                 return Qnil;
3104
3105         return split_string_by_emchar_1(newpath, newlen, SEPCHAR);
3106 }
3107
3108 Lisp_Object decode_env_path(const char *evarname, /*const*/ char *default_)
3109 {
3110         /*const*/ char *path = 0;
3111         if (evarname)
3112                 path = egetenv(evarname);
3113         if (!path)
3114                 path = default_;
3115         return decode_path(path);
3116 }
3117
3118 /* Ben thinks this function should not exist or be exported to Lisp.
3119    We use it to define split-path-string in subr.el (not!).  */
3120
3121 DEFUN("split-string-by-char", Fsplit_string_by_char, 2, 2, 0, /*
3122 Split STRING into a list of substrings originally separated by SEPCHAR.
3123 */
3124       (string, sepchar))
3125 {
3126         CHECK_STRING(string);
3127         CHECK_CHAR(sepchar);
3128         return split_string_by_emchar_1(XSTRING_DATA(string),
3129                                         XSTRING_LENGTH(string), XCHAR(sepchar));
3130 }
3131
3132 /* #### This was supposed to be in subr.el, but is used VERY early in
3133    the bootstrap process, so it goes here.  Damn.  */
3134
3135 DEFUN("split-path", Fsplit_path, 1, 1, 0, /*
3136 Explode a search path into a list of strings.
3137 The path components are separated with the characters specified
3138 with `path-separator'.
3139 */
3140       (path))
3141 {
3142         CHECK_STRING(path);
3143
3144         while (!STRINGP(Vpath_separator)
3145                || (XSTRING_CHAR_LENGTH(Vpath_separator) != 1))
3146                 Vpath_separator = signal_simple_continuable_error
3147                     ("`path-separator' should be set to a single-character string",
3148                      Vpath_separator);
3149
3150         return (split_string_by_emchar_1
3151                 (XSTRING_DATA(path), XSTRING_LENGTH(path),
3152                  charptr_emchar(XSTRING_DATA(Vpath_separator))));
3153 }
3154 \f
3155 DEFUN("noninteractive", Fnoninteractive, 0, 0, 0, /*
3156 Non-nil return value means SXEmacs is running without interactive terminal.
3157 */
3158       ())
3159 {
3160         return noninteractive ? Qt : Qnil;
3161 }
3162
3163 #ifdef USE_ASSERTIONS
3164 static int in_assert_failed = 0;
3165 static const char *assert_failed_file = NULL;
3166 static int assert_failed_line = 0;
3167 static const char *assert_failed_expr = NULL;
3168 /* This flag is useful to define if you're under a debugger; this way, you
3169    can put a breakpoint of assert_failed() and debug multiple problems
3170    in one session without having to recompile. */
3171 static int assertions_dont_abort = 0;
3172
3173 #ifdef fprintf
3174 #undef fprintf
3175 #endif
3176
3177 #ifdef abort
3178 #undef abort                    /* avoid infinite #define loop... */
3179 #endif
3180
3181 #define enter_debugger()
3182
3183 void
3184 assert_failed(const char *file, int line, const char *expr)
3185 {
3186         /* If we're already crashing, let's not crash again.  This might be
3187            critical to getting auto-saving working properly. */
3188         if (fatal_error_in_progress)
3189                 return;
3190
3191         /* We are extremely paranoid so we sensibly deal with recursive
3192            assertion failures. */
3193         in_assert_failed++;
3194         inhibit_non_essential_printing_operations = 1;
3195
3196         if (in_assert_failed >= 4)
3197                 _exit(-1);
3198         else if (in_assert_failed == 3) {
3199                 enter_debugger();
3200                 abort();
3201         } else if (in_assert_failed == 2) {
3202                 /* Not stderr_out(), which does additional things and may trigger
3203                    a recursive assertion failure.  fprintf was undeffed above, in
3204                    case it was encapsulated. */
3205                 fprintf(stderr,
3206                         "\n\nFatal error: recursive assertion failure, "
3207                         "file %s, line %d, %s\n", file, line, expr);
3208                 fprintf(stderr,
3209                         "Original assertion failure: file %s, line %d, %s\n",
3210                         assert_failed_file, assert_failed_line,
3211                         assert_failed_expr);
3212                 fflush(stderr);
3213                 enter_debugger();
3214                 debug_short_backtrace(0x7FFF);
3215         } else {
3216                 assert_failed_file = file;
3217                 assert_failed_line = line;
3218                 assert_failed_expr = expr;
3219
3220                 if (!initialized)
3221                         fprintf(stderr,
3222                                 "\nFatal error: assertion failed, file %s, line %d, %s\n",
3223                                 file, line, expr);
3224                 else
3225                         stderr_out
3226                             ("\nFatal error: assertion failed, file %s, line %d, %s\n",
3227                              file, line, expr);
3228                 fflush(stderr);
3229                 enter_debugger();
3230                 debug_backtrace();
3231         }
3232         if (! assertions_dont_abort) {
3233                 abort();
3234         }
3235         inhibit_non_essential_printing_operations = 0;
3236         in_assert_failed = 0;
3237 }
3238 #endif                          /* USE_ASSERTIONS */
3239
3240 #ifdef QUANTIFY
3241 DEFUN("quantify-start-recording-data", Fquantify_start_recording_data, 0, 0, "", /*
3242 Start recording Quantify data.
3243 */
3244       ())
3245 {
3246         quantify_start_recording_data();
3247         return Qnil;
3248 }
3249
3250 DEFUN("quantify-stop-recording-data", Fquantify_stop_recording_data, 0, 0, "", /*
3251 Stop recording Quantify data.
3252 */
3253       ())
3254 {
3255         quantify_stop_recording_data();
3256         return Qnil;
3257 }
3258
3259 DEFUN("quantify-clear-data", Fquantify_clear_data, 0, 0, "", /*
3260 Clear all Quantify data.
3261 */
3262       ())
3263 {
3264         quantify_clear_data();
3265         return Qnil;
3266 }
3267 #endif                          /* QUANTIFY */
3268
3269 void syms_of_emacs(void)
3270 {
3271 #ifndef CANNOT_DUMP
3272         DEFSUBR(Fdump_emacs);
3273 #endif                          /* !CANNOT_DUMP */
3274
3275         DEFSUBR(Frun_emacs_from_temacs);
3276         DEFSUBR(Frunning_temacs_p);
3277         DEFSUBR(Finvocation_name);
3278         DEFSUBR(Finvocation_directory);
3279         DEFSUBR(Fkill_emacs);
3280         DEFSUBR(Fnoninteractive);
3281
3282 #ifdef DEBUG_SXEMACS
3283         DEFSUBR(Fforce_debugging_signal);
3284 #endif
3285
3286 #ifdef QUANTIFY
3287         DEFSUBR(Fquantify_start_recording_data);
3288         DEFSUBR(Fquantify_stop_recording_data);
3289         DEFSUBR(Fquantify_clear_data);
3290 #endif                          /* QUANTIFY */
3291
3292         DEFSUBR(Fsplit_string_by_char);
3293         DEFSUBR(Fsplit_path);   /* #### */
3294
3295         defsymbol(&Qkill_emacs_hook, "kill-emacs-hook");
3296         defsymbol(&Qsave_buffers_kill_emacs, "save-buffers-kill-emacs");
3297 }
3298
3299 void vars_of_emacs(void)
3300 {
3301         DEFVAR_BOOL("suppress-early-error-handler-backtrace", &suppress_early_error_handler_backtrace /*
3302 Non-nil means early error handler shouldn't print a backtrace.
3303                                                                                                       */ );
3304
3305         DEFVAR_LISP("command-line-args", &Vcommand_line_args /*
3306 Args passed by shell to SXEmacs, as a list of strings.
3307                                                              */ );
3308
3309         DEFVAR_LISP("invocation-name", &Vinvocation_name /*
3310 The program name that was used to run SXEmacs.
3311 Any directory names are omitted.
3312                                                          */ );
3313
3314         DEFVAR_LISP("invocation-directory", &Vinvocation_directory /*
3315 The directory in which the SXEmacs executable was found, to run it.
3316 The value is simply the program name if that directory's name is not known.
3317                                                                    */ );
3318
3319         DEFVAR_LISP("invocation-path", &Vinvocation_path /*
3320 The path in which the SXEmacs executable was found, to run it.
3321 The value is simply the value of environment variable PATH on startup
3322 if SXEmacs was found there.
3323                                                          */ );
3324
3325 #if 0                           /* FSFmacs */
3326         xxDEFVAR_LISP("installation-directory", &Vinstallation_directory,
3327                       "A directory within which to look for the `lib-src' and `etc' directories.\n"
3328                       "This is non-nil when we can't find those directories in their standard\n"
3329                       "installed locations, but we can find them\n"
3330                       "near where the SXEmacs executable was found.");
3331 #endif
3332
3333         DEFVAR_LISP("system-type", &Vsystem_type /*
3334 Symbol indicating type of operating system you are using.
3335                                                  */ );
3336         Vsystem_type = intern(SYSTEM_TYPE);
3337         Fprovide(intern(SYSTEM_TYPE));
3338
3339 #ifndef EMACS_CONFIGURATION
3340 # define EMACS_CONFIGURATION "UNKNOWN"
3341 #endif
3342         DEFVAR_LISP("system-configuration", &Vsystem_configuration /*
3343 String naming the configuration SXEmacs was built for.
3344                                                                    */ );
3345         Vsystem_configuration = build_string(EMACS_CONFIGURATION);
3346
3347 #ifndef EMACS_CONFIG_OPTIONS
3348 # define EMACS_CONFIG_OPTIONS "UNKNOWN"
3349 #endif
3350         DEFVAR_LISP("system-configuration-options", &Vsystem_configuration_options /*
3351 String containing the configuration options SXEmacs was built with.
3352                                                                                    */ );
3353         Vsystem_configuration_options = build_string(EMACS_CONFIG_OPTIONS);
3354
3355         DEFVAR_LISP("emacs-major-version", &Vemacs_major_version /*
3356 Major version number of this version of Emacs, as an integer.
3357 Warning: this variable did not exist in Emacs versions earlier than:
3358   FSF Emacs:   19.23
3359   XEmacs:      19.10
3360                                                                  */ );
3361         Vemacs_major_version = make_int(EMACS_MAJOR_VERSION);
3362
3363         DEFVAR_LISP("emacs-minor-version", &Vemacs_minor_version /*
3364 Minor version number of this version of Emacs, as an integer.
3365 Warning: this variable did not exist in Emacs versions earlier than:
3366   FSF Emacs:   19.23
3367   XEmacs:      19.10
3368                                                                  */ );
3369         Vemacs_minor_version = make_int(EMACS_MINOR_VERSION);
3370
3371         DEFVAR_LISP("emacs-patch-level", &Vemacs_patch_level /*
3372 The patch level of this version of Emacs, as an integer.
3373 The value is non-nil if this version of SXEmacs is part of a series of
3374 stable SXEmacsen, but has bug fixes applied.
3375 Warning: this variable does not exist in FSF Emacs or in XEmacs versions
3376 earlier than 21.1.1
3377                                                              */ );
3378 #ifdef EMACS_PATCH_LEVEL
3379         Vemacs_patch_level = make_int(EMACS_PATCH_LEVEL);
3380 #else
3381         Vemacs_patch_level = Qnil;
3382 #endif
3383
3384         DEFVAR_LISP("emacs-beta-version", &Vemacs_beta_version /*
3385 Beta number of this version of Emacs, as an integer.
3386 The value is nil if this is an officially released version of SXEmacs.
3387 Warning: this variable does not exist in FSF Emacs or in XEmacs versions
3388 earlier than 20.3.
3389                                                                */ );
3390 #ifdef EMACS_BETA_VERSION
3391         Vemacs_beta_version = make_int(EMACS_BETA_VERSION);
3392 #else
3393         Vemacs_beta_version = Qnil;
3394 #endif
3395
3396         DEFVAR_LISP("sxemacs-git-version", &Vsxemacs_git_version /*
3397 This revision name of this SXEmacs.
3398 Warning: this variable does not exist in FSF Emacs or XEmacs.
3399                                                                    */ );
3400
3401         Vsxemacs_git_version = build_string(SXEMACS_GIT_VERSION);
3402
3403 #ifdef INFODOCK
3404         DEFVAR_LISP("infodock-major-version", &Vinfodock_major_version /*
3405 Major version number of this InfoDock release.
3406                                                                        */ );
3407         Vinfodock_major_version = make_int(INFODOCK_MAJOR_VERSION);
3408
3409         DEFVAR_LISP("infodock-minor-version", &Vinfodock_minor_version /*
3410 Minor version number of this InfoDock release.
3411                                                                        */ );
3412         Vinfodock_minor_version = make_int(INFODOCK_MINOR_VERSION);
3413
3414         DEFVAR_LISP("infodock-build-version", &Vinfodock_build_version /*
3415 Build version of this InfoDock release.
3416                                                                        */ );
3417         Vinfodock_build_version = make_int(INFODOCK_BUILD_VERSION);
3418 #endif
3419
3420         DEFVAR_LISP("sxemacs-codename", &Vsxemacs_codename /*
3421 Codename of this version of SXEmacs (a string).
3422                                                            */ );
3423 #ifndef SXEMACS_CODENAME
3424 #define SXEMACS_CODENAME "Noname"
3425 #endif
3426         Vsxemacs_codename = build_string(SXEMACS_CODENAME);
3427
3428         /* Lisp variables which contain command line flags.
3429
3430            The portable dumper stomps on these; they must be saved and restored
3431            if they are processed before the call to pdump_load() in main_1().
3432          */
3433         DEFVAR_BOOL("noninteractive", &noninteractive1 /*
3434 Non-nil means SXEmacs is running without interactive terminal.
3435                                                        */ );
3436
3437         DEFVAR_BOOL("inhibit-early-packages", &inhibit_early_packages /*
3438 Set to non-nil when the early packages should not be respected at startup.
3439                                                                       */ );
3440         DEFVAR_BOOL("warn-early-package-shadows", &warn_early_package_shadows /*
3441 Set to non-nil when the early packages should not shadow late packages. Issues
3442 warning at startup when that happens.
3443                                                                               */ );
3444         warn_early_package_shadows = 0;
3445
3446         DEFVAR_BOOL("inhibit-autoloads", &inhibit_autoloads /*
3447  Set to non-nil when autoloads should not be loaded at startup.
3448                                                             */ );
3449
3450         DEFVAR_BOOL("debug-paths", &debug_paths /*
3451 Set to non-nil when debug information about paths should be printed.
3452                                                  */ );
3453
3454         DEFVAR_BOOL("inhibit-site-modules", &inhibit_site_modules /*
3455 Set to non-nil when site-modules should not be searched at startup.
3456                                                                   */ );
3457 #ifdef INHIBIT_SITE_MODULES
3458         inhibit_site_modules = 1;
3459 #endif
3460
3461         DEFVAR_INT("emacs-priority", &emacs_priority /*
3462 Priority for SXEmacs to run at.
3463 This value is effective only if set before SXEmacs is dumped,
3464 and only if the SXEmacs executable is installed with setuid to permit
3465 it to change priority.  (SXEmacs sets its uid back to the real uid.)
3466 Currently, you need to define SET_EMACS_PRIORITY in `config.h'
3467 before you compile SXEmacs, to enable the code for this feature.
3468                                                      */ );
3469         emacs_priority = 0;
3470
3471         DEFVAR_CONST_LISP("internal-error-checking", &Vinternal_error_checking /*
3472 Internal error checking built-in into this instance of SXEmacs.
3473 This is a list of symbols, initialized at build-time.  Legal symbols
3474 are:
3475    extents     - check extents prior to each extent change;
3476    typecheck   - check types strictly, aborting in case of error;
3477    malloc      - check operation of malloc;
3478    gc          - check garbage collection;
3479    bufpos      - check buffer positions.
3480    quick-build - user has requested the "quick-build" configure option.
3481                                                                                */ );
3482         Vinternal_error_checking = Qnil;
3483 #ifdef ERROR_CHECK_EXTENTS
3484         Vinternal_error_checking = Fcons(intern("extents"),
3485                                          Vinternal_error_checking);
3486 #endif
3487 #ifdef ERROR_CHECK_TYPECHECK
3488         Vinternal_error_checking = Fcons(intern("typecheck"),
3489                                          Vinternal_error_checking);
3490 #endif
3491 #ifdef ERROR_CHECK_MALLOC
3492         Vinternal_error_checking = Fcons(intern("malloc"),
3493                                          Vinternal_error_checking);
3494 #endif
3495 #ifdef ERROR_CHECK_GC
3496         Vinternal_error_checking = Fcons(intern("gc"),
3497                                          Vinternal_error_checking);
3498 #endif
3499 #ifdef ERROR_CHECK_BUFPOS
3500         Vinternal_error_checking = Fcons(intern("bufpos"),
3501                                          Vinternal_error_checking);
3502 #endif
3503 #ifdef QUICK_BUILD
3504         Vinternal_error_checking = Fcons(intern("quick-build"),
3505                                          Vinternal_error_checking);
3506 #endif
3507
3508         DEFVAR_CONST_LISP("mail-lock-methods", &Vmail_lock_methods /*
3509 Mail spool locking methods supported by this instance of SXEmacs.
3510 This is a list of symbols.  Each of the symbols is one of the
3511 following: dot, lockf, flock, locking, mmdf.
3512                                                                    */ );
3513         {
3514                 Vmail_lock_methods = Qnil;
3515                 Vmail_lock_methods = Fcons(intern("dot"), Vmail_lock_methods);
3516 #ifdef HAVE_LOCKF
3517                 Vmail_lock_methods = Fcons(intern("lockf"), Vmail_lock_methods);
3518 #endif
3519 #ifdef HAVE_FLOCK
3520                 Vmail_lock_methods = Fcons(intern("flock"), Vmail_lock_methods);
3521 #endif
3522 #ifdef HAVE_MMDF
3523                 Vmail_lock_methods = Fcons(intern("mmdf"), Vmail_lock_methods);
3524 #endif
3525 #ifdef HAVE_LOCKING
3526                 Vmail_lock_methods =
3527                     Fcons(intern("locking"), Vmail_lock_methods);
3528 #endif
3529         }
3530
3531         DEFVAR_CONST_LISP("configure-mail-lock-method", &Vconfigure_mail_lock_method /*
3532 Mail spool locking method suggested by configure.  This is one
3533 of the symbols in MAIL-LOCK-METHODS.
3534                                                                                      */ );
3535         {
3536 #if defined(MAIL_LOCK_FLOCK) && defined(HAVE_FLOCK)
3537                 Vconfigure_mail_lock_method = intern("flock");
3538 #elif defined(MAIL_LOCK_LOCKF) && defined(HAVE_LOCKF)
3539                 Vconfigure_mail_lock_method = intern("lockf");
3540 #elif defined(MAIL_LOCK_MMDF) && defined(HAVE_MMDF)
3541                 Vconfigure_mail_lock_method = intern("mmdf");
3542 #elif defined(MAIL_LOCK_LOCKING) && defined(HAVE_LOCKING)
3543                 Vconfigure_mail_lock_method = intern("locking");
3544 #else
3545                 Vconfigure_mail_lock_method = intern("dot");
3546 #endif
3547         }
3548
3549         DEFVAR_LISP("path-separator", &Vpath_separator /*
3550 The directory separator in search paths, as a string.
3551                                                        */ );
3552         {
3553                 char c = SEPCHAR;
3554                 Vpath_separator = make_string((Bufbyte *) & c, 1);
3555         }
3556 }
3557
3558 void complex_vars_of_emacs(void)
3559 {
3560         /* This is all related to path searching. */
3561
3562         DEFVAR_LISP("emacs-program-name", &Vemacs_program_name /*
3563 *Name of the Emacs variant.
3564 For example, this may be \"sxemacs\" or \"infodock\".
3565 This is mainly meant for use in path searching.
3566                                                                */ );
3567         Vemacs_program_name = build_string((char *)PATH_PROGNAME);
3568
3569         DEFVAR_LISP("emacs-program-version", &Vemacs_program_version /*
3570 *Version of the Emacs variant.
3571 This typically has the form NN.NN-bNN.
3572 This is mainly meant for use in path searching.
3573                                                                      */ );
3574         Vemacs_program_version = build_string((char *)PATH_VERSION);
3575
3576         DEFVAR_LISP("exec-path", &Vexec_path /*
3577 *List of directories to search programs to run in subprocesses.
3578 Each element is a string (directory name) or nil (try default directory).
3579                                              */ );
3580         Vexec_path = Qnil;
3581
3582         DEFVAR_LISP("exec-directory", &Vexec_directory /*
3583 *Directory of architecture-dependent files that come with SXEmacs,
3584 especially executable programs intended for SXEmacs to invoke.
3585                                                        */ );
3586         Vexec_directory = Qnil;
3587
3588         DEFVAR_LISP("configure-exec-directory", &Vconfigure_exec_directory /*
3589 For internal use by the build procedure only.
3590 configure's idea of what `exec-directory' will be.
3591                                                                            */ );
3592 #ifdef PATH_EXEC
3593         Vconfigure_exec_directory = Ffile_name_as_directory
3594             (build_string((char *)PATH_EXEC));
3595 #else
3596         Vconfigure_exec_directory = Qnil;
3597 #endif
3598
3599         DEFVAR_LISP("lisp-directory", &Vlisp_directory /*
3600 *Directory of core Lisp files that come with SXEmacs.
3601 */ );
3602         Vlisp_directory = Qnil;
3603
3604         DEFVAR_LISP("configure-lisp-directory", &Vconfigure_lisp_directory /*
3605 For internal use by the build procedure only.
3606 configure's idea of what `lisp-directory' will be.
3607                                                                            */ );
3608 #ifdef PATH_LOADSEARCH
3609         Vconfigure_lisp_directory = Ffile_name_as_directory
3610             (build_string((char *)PATH_LOADSEARCH));
3611 #else
3612         Vconfigure_lisp_directory = Qnil;
3613 #endif
3614
3615         DEFVAR_LISP("mule-lisp-directory", &Vmule_lisp_directory /*
3616 *Directory of Mule Lisp files that come with SXEmacs.
3617 */ );
3618         Vmule_lisp_directory = Qnil;
3619
3620         DEFVAR_LISP("configure-mule-lisp-directory", &Vconfigure_mule_lisp_directory /*
3621 For internal use by the build procedure only.
3622 configure's idea of what `mule-lisp-directory' will be.
3623                                                                                      */ );
3624 #ifdef PATH_MULELOADSEARCH
3625         Vconfigure_mule_lisp_directory = Ffile_name_as_directory
3626             (build_string((char *)PATH_MULELOADSEARCH));
3627 #else
3628         Vconfigure_mule_lisp_directory = Qnil;
3629 #endif
3630
3631         DEFVAR_LISP("module-directory", &Vmodule_directory /*
3632 *Directory of core dynamic modules that come with SXEmacs.
3633 */ );
3634         Vmodule_directory = Qnil;
3635
3636         DEFVAR_LISP("configure-module-directory", &Vconfigure_module_directory /*
3637 For internal use by the build procedure only.
3638 configure's idea of what `module-directory' will be.
3639                                                                                */ );
3640 #ifdef PATH_MODULESEARCH
3641         Vconfigure_module_directory = Ffile_name_as_directory
3642             (build_string((char *)PATH_MODULESEARCH));
3643 #else
3644         Vconfigure_module_directory = Qnil;
3645 #endif
3646
3647         DEFVAR_LISP("configure-package-path", &Vconfigure_package_path /*
3648 For internal use by the build procedure only.
3649 configure's idea of what the package path will be.
3650                                                                        */ );
3651 #ifdef PATH_PACKAGEPATH
3652         Vconfigure_package_path = decode_path(PATH_PACKAGEPATH);
3653 #else
3654         Vconfigure_package_path = Qnil;
3655 #endif
3656
3657         DEFVAR_LISP("data-directory", &Vdata_directory /*
3658 *Directory of architecture-independent files that come with SXEmacs,
3659 intended for SXEmacs to use.
3660 Use of this variable in new code is almost never correct.  See the
3661 functions `locate-data-file' and `locate-data-directory' and the variable
3662 `data-directory-list'.
3663                                                        */ );
3664         Vdata_directory = Qnil;
3665
3666         DEFVAR_LISP("configure-data-directory", &Vconfigure_data_directory /*
3667 For internal use by the build procedure only.
3668 configure's idea of what `data-directory' will be.
3669                                                                            */ );
3670 #ifdef PATH_DATA
3671         Vconfigure_data_directory = Ffile_name_as_directory
3672             (build_string((char *)PATH_DATA));
3673 #else
3674         Vconfigure_data_directory = Qnil;
3675 #endif
3676
3677         DEFVAR_LISP("data-directory-list", &Vdata_directory_list /*
3678 *List of directories of architecture-independent files that come with SXEmacs
3679 or were installed as packages, and are intended for SXEmacs to use.
3680                                                                  */ );
3681         Vdata_directory_list = Qnil;
3682
3683         DEFVAR_LISP("site-module-directory", &Vsite_module_directory /*
3684 *Directory of site-specific loadable modules that come with SXEmacs.
3685 */ );
3686         Vsite_module_directory = Qnil;
3687
3688         DEFVAR_LISP("configure-site-module-directory", &Vconfigure_site_module_directory /*
3689 For internal use by the build procedure only.
3690 configure's idea of what `site-directory' will be.
3691                                                                                          */ );
3692 #ifdef PATH_SITE_MODULES
3693         Vconfigure_site_module_directory = Ffile_name_as_directory
3694             (build_string((char *)PATH_SITE_MODULES));
3695 #else
3696         Vconfigure_site_module_directory = Qnil;
3697 #endif
3698
3699         DEFVAR_LISP("doc-directory", &Vdoc_directory /*
3700 *Directory containing the DOC file that comes with SXEmacs.
3701 This is usually the same as `exec-directory'.
3702                                                      */ );
3703         Vdoc_directory = Qnil;
3704
3705         DEFVAR_LISP("configure-doc-directory", &Vconfigure_doc_directory /*
3706 For internal use by the build procedure only.
3707 configure's idea of what `doc-directory' will be.
3708                                                                          */ );
3709 #ifdef PATH_DOC
3710         Vconfigure_doc_directory = Ffile_name_as_directory
3711             (build_string((char *)PATH_DOC));
3712 #else
3713         Vconfigure_doc_directory = Qnil;
3714 #endif
3715
3716         DEFVAR_LISP("configure-exec-prefix-directory", &Vconfigure_exec_prefix_directory /*
3717 For internal use by the build procedure only.
3718 configure's idea of what `exec-prefix-directory' will be.
3719                                                                                          */ );
3720 #ifdef PATH_EXEC_PREFIX
3721         Vconfigure_exec_prefix_directory = Ffile_name_as_directory
3722             (build_string((char *)PATH_EXEC_PREFIX));
3723 #else
3724         Vconfigure_exec_prefix_directory = Qnil;
3725 #endif
3726
3727         DEFVAR_LISP("configure-prefix-directory", &Vconfigure_prefix_directory /*
3728 For internal use by the build procedure only.
3729 configure's idea of what `prefix-directory' will be.
3730                                                                                */ );
3731 #ifdef PATH_PREFIX
3732         Vconfigure_prefix_directory = Ffile_name_as_directory
3733             (build_string((char *)PATH_PREFIX));
3734 #else
3735         Vconfigure_prefix_directory = Qnil;
3736 #endif
3737
3738         DEFVAR_LISP("configure-info-directory", &Vconfigure_info_directory /*
3739 For internal use by the build procedure only.
3740 This is the name of the directory in which the build procedure installed
3741 Emacs's info files; the default value for Info-default-directory-list
3742 includes this.
3743                                                                            */ );
3744 #ifdef PATH_INFO
3745         Vconfigure_info_directory =
3746             Ffile_name_as_directory(build_string(PATH_INFO));
3747 #else
3748         Vconfigure_info_directory = Qnil;
3749 #endif
3750
3751         DEFVAR_LISP("configure-info-path", &Vconfigure_info_path /*
3752 The configured initial path for info documentation.
3753                                                                  */ );
3754 #ifdef PATH_INFOPATH
3755         Vconfigure_info_path = decode_path(PATH_INFOPATH);
3756 #else
3757         Vconfigure_info_path = Qnil;
3758 #endif
3759 }
3760
3761 #if defined(__sgi) && !defined(PDUMP)
3762 /* This is so tremendously ugly I'd puke. But then, it works.
3763  * The target is to override the static constructor from the
3764  * libiflPNG.so library which is masquerading as libz, and
3765  * cores on us when re-started from the dumped executable.
3766  * This will have to go for 21.1  -- OG.
3767  */
3768 void __sti__iflPNGFile_c___(void);
3769 void __sti__iflPNGFile_c___(void)
3770 {
3771 }
3772
3773 #endif