Mercurial > hg > xemacs-beta
view lib-src/ellcc.c @ 5127:a9c41067dd88 ben-lisp-object
more cleanups, terminology clarification, lots of doc work
-------------------- ChangeLog entries follow: --------------------
man/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* internals/internals.texi (Introduction to Allocation):
* internals/internals.texi (Integers and Characters):
* internals/internals.texi (Allocation from Frob Blocks):
* internals/internals.texi (lrecords):
* internals/internals.texi (Low-level allocation):
Rewrite section on allocation of Lisp objects to reflect the new
reality. Remove references to nonexistent XSETINT and XSETCHAR.
modules/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c (allocate_pgconn):
* postgresql/postgresql.c (allocate_pgresult):
* postgresql/postgresql.h (struct Lisp_PGconn):
* postgresql/postgresql.h (struct Lisp_PGresult):
* ldap/eldap.c (allocate_ldap):
* ldap/eldap.h (struct Lisp_LDAP):
Same changes as in src/ dir. See large log there in ChangeLog,
but basically:
ALLOC_LISP_OBJECT -> ALLOC_NORMAL_LISP_OBJECT
LISP_OBJECT_HEADER -> NORMAL_LISP_OBJECT_HEADER
../hlo/src/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (old_alloc_sized_lcrecord):
* alloc.c (very_old_free_lcrecord):
* alloc.c (copy_lisp_object):
* alloc.c (zero_sized_lisp_object):
* alloc.c (zero_nonsized_lisp_object):
* alloc.c (lisp_object_storage_size):
* alloc.c (free_normal_lisp_object):
* alloc.c (FREE_FIXED_TYPE_WHEN_NOT_IN_GC):
* alloc.c (ALLOC_FROB_BLOCK_LISP_OBJECT):
* alloc.c (Fcons):
* alloc.c (noseeum_cons):
* alloc.c (make_float):
* alloc.c (make_bignum):
* alloc.c (make_bignum_bg):
* alloc.c (make_ratio):
* alloc.c (make_ratio_bg):
* alloc.c (make_ratio_rt):
* alloc.c (make_bigfloat):
* alloc.c (make_bigfloat_bf):
* alloc.c (size_vector):
* alloc.c (make_compiled_function):
* alloc.c (Fmake_symbol):
* alloc.c (allocate_extent):
* alloc.c (allocate_event):
* alloc.c (make_key_data):
* alloc.c (make_button_data):
* alloc.c (make_motion_data):
* alloc.c (make_process_data):
* alloc.c (make_timeout_data):
* alloc.c (make_magic_data):
* alloc.c (make_magic_eval_data):
* alloc.c (make_eval_data):
* alloc.c (make_misc_user_data):
* alloc.c (Fmake_marker):
* alloc.c (noseeum_make_marker):
* alloc.c (size_string_direct_data):
* alloc.c (make_uninit_string):
* alloc.c (make_string_nocopy):
* alloc.c (mark_lcrecord_list):
* alloc.c (alloc_managed_lcrecord):
* alloc.c (free_managed_lcrecord):
* alloc.c (sweep_lcrecords_1):
* alloc.c (malloced_storage_size):
* buffer.c (allocate_buffer):
* buffer.c (compute_buffer_usage):
* buffer.c (DEFVAR_BUFFER_LOCAL_1):
* buffer.c (nuke_all_buffer_slots):
* buffer.c (common_init_complex_vars_of_buffer):
* buffer.h (struct buffer_text):
* buffer.h (struct buffer):
* bytecode.c:
* bytecode.c (make_compiled_function_args):
* bytecode.c (size_compiled_function_args):
* bytecode.h (struct compiled_function_args):
* casetab.c (allocate_case_table):
* casetab.h (struct Lisp_Case_Table):
* charset.h (struct Lisp_Charset):
* chartab.c (fill_char_table):
* chartab.c (Fmake_char_table):
* chartab.c (make_char_table_entry):
* chartab.c (copy_char_table_entry):
* chartab.c (Fcopy_char_table):
* chartab.c (put_char_table):
* chartab.h (struct Lisp_Char_Table_Entry):
* chartab.h (struct Lisp_Char_Table):
* console-gtk-impl.h (struct gtk_device):
* console-gtk-impl.h (struct gtk_frame):
* console-impl.h (struct console):
* console-msw-impl.h (struct Lisp_Devmode):
* console-msw-impl.h (struct mswindows_device):
* console-msw-impl.h (struct msprinter_device):
* console-msw-impl.h (struct mswindows_frame):
* console-msw-impl.h (struct mswindows_dialog_id):
* console-stream-impl.h (struct stream_console):
* console-stream.c (stream_init_console):
* console-tty-impl.h (struct tty_console):
* console-tty-impl.h (struct tty_device):
* console-tty.c (allocate_tty_console_struct):
* console-x-impl.h (struct x_device):
* console-x-impl.h (struct x_frame):
* console.c (allocate_console):
* console.c (nuke_all_console_slots):
* console.c (DEFVAR_CONSOLE_LOCAL_1):
* console.c (common_init_complex_vars_of_console):
* data.c (make_weak_list):
* data.c (make_weak_box):
* data.c (make_ephemeron):
* database.c:
* database.c (struct Lisp_Database):
* database.c (allocate_database):
* database.c (finalize_database):
* device-gtk.c (allocate_gtk_device_struct):
* device-impl.h (struct device):
* device-msw.c:
* device-msw.c (mswindows_init_device):
* device-msw.c (msprinter_init_device):
* device-msw.c (finalize_devmode):
* device-msw.c (allocate_devmode):
* device-tty.c (allocate_tty_device_struct):
* device-x.c (allocate_x_device_struct):
* device.c:
* device.c (nuke_all_device_slots):
* device.c (allocate_device):
* dialog-msw.c (handle_question_dialog_box):
* elhash.c:
* elhash.c (struct Lisp_Hash_Table):
* elhash.c (finalize_hash_table):
* elhash.c (make_general_lisp_hash_table):
* elhash.c (Fcopy_hash_table):
* elhash.h (htentry):
* emacs.c (main_1):
* eval.c:
* eval.c (size_multiple_value):
* event-stream.c (finalize_command_builder):
* event-stream.c (allocate_command_builder):
* event-stream.c (free_command_builder):
* event-stream.c (event_stream_generate_wakeup):
* event-stream.c (event_stream_resignal_wakeup):
* event-stream.c (event_stream_disable_wakeup):
* event-stream.c (event_stream_wakeup_pending_p):
* events.h (struct Lisp_Timeout):
* events.h (struct command_builder):
* extents-impl.h:
* extents-impl.h (struct extent_auxiliary):
* extents-impl.h (struct extent_info):
* extents-impl.h (set_extent_no_chase_aux_field):
* extents-impl.h (set_extent_no_chase_normal_field):
* extents.c:
* extents.c (gap_array_marker):
* extents.c (gap_array):
* extents.c (extent_list_marker):
* extents.c (extent_list):
* extents.c (stack_of_extents):
* extents.c (gap_array_make_marker):
* extents.c (extent_list_make_marker):
* extents.c (allocate_extent_list):
* extents.c (SLOT):
* extents.c (mark_extent_auxiliary):
* extents.c (allocate_extent_auxiliary):
* extents.c (attach_extent_auxiliary):
* extents.c (size_gap_array):
* extents.c (finalize_extent_info):
* extents.c (allocate_extent_info):
* extents.c (uninit_buffer_extents):
* extents.c (allocate_soe):
* extents.c (copy_extent):
* extents.c (vars_of_extents):
* extents.h:
* faces.c (allocate_face):
* faces.h (struct Lisp_Face):
* faces.h (struct face_cachel):
* file-coding.c:
* file-coding.c (finalize_coding_system):
* file-coding.c (sizeof_coding_system):
* file-coding.c (Fcopy_coding_system):
* file-coding.h (struct Lisp_Coding_System):
* file-coding.h (MARKED_SLOT):
* fns.c (size_bit_vector):
* font-mgr.c:
* font-mgr.c (finalize_fc_pattern):
* font-mgr.c (print_fc_pattern):
* font-mgr.c (Ffc_pattern_p):
* font-mgr.c (Ffc_pattern_create):
* font-mgr.c (Ffc_name_parse):
* font-mgr.c (Ffc_name_unparse):
* font-mgr.c (Ffc_pattern_duplicate):
* font-mgr.c (Ffc_pattern_add):
* font-mgr.c (Ffc_pattern_del):
* font-mgr.c (Ffc_pattern_get):
* font-mgr.c (fc_config_create_using):
* font-mgr.c (fc_strlist_to_lisp_using):
* font-mgr.c (fontset_to_list):
* font-mgr.c (Ffc_config_p):
* font-mgr.c (Ffc_config_up_to_date):
* font-mgr.c (Ffc_config_build_fonts):
* font-mgr.c (Ffc_config_get_cache):
* font-mgr.c (Ffc_config_get_fonts):
* font-mgr.c (Ffc_config_set_current):
* font-mgr.c (Ffc_config_get_blanks):
* font-mgr.c (Ffc_config_get_rescan_interval):
* font-mgr.c (Ffc_config_set_rescan_interval):
* font-mgr.c (Ffc_config_app_font_add_file):
* font-mgr.c (Ffc_config_app_font_add_dir):
* font-mgr.c (Ffc_config_app_font_clear):
* font-mgr.c (size):
* font-mgr.c (Ffc_config_substitute):
* font-mgr.c (Ffc_font_render_prepare):
* font-mgr.c (Ffc_font_match):
* font-mgr.c (Ffc_font_sort):
* font-mgr.c (finalize_fc_config):
* font-mgr.c (print_fc_config):
* font-mgr.h:
* font-mgr.h (struct fc_pattern):
* font-mgr.h (XFC_PATTERN):
* font-mgr.h (struct fc_config):
* font-mgr.h (XFC_CONFIG):
* frame-gtk.c (allocate_gtk_frame_struct):
* frame-impl.h (struct frame):
* frame-msw.c (mswindows_init_frame_1):
* frame-x.c (allocate_x_frame_struct):
* frame.c (nuke_all_frame_slots):
* frame.c (allocate_frame_core):
* gc.c:
* gc.c (GC_CHECK_NOT_FREE):
* glyphs.c (finalize_image_instance):
* glyphs.c (allocate_image_instance):
* glyphs.c (Fcolorize_image_instance):
* glyphs.c (allocate_glyph):
* glyphs.c (unmap_subwindow_instance_cache_mapper):
* glyphs.c (register_ignored_expose):
* glyphs.h (struct Lisp_Image_Instance):
* glyphs.h (struct Lisp_Glyph):
* glyphs.h (struct glyph_cachel):
* glyphs.h (struct expose_ignore):
* gui.c (allocate_gui_item):
* gui.h (struct Lisp_Gui_Item):
* keymap.c (struct Lisp_Keymap):
* keymap.c (make_keymap):
* lisp.h:
* lisp.h (struct Lisp_String_Direct_Data):
* lisp.h (struct Lisp_String_Indirect_Data):
* lisp.h (struct Lisp_Vector):
* lisp.h (struct Lisp_Bit_Vector):
* lisp.h (DECLARE_INLINE_LISP_BIT_VECTOR):
* lisp.h (struct weak_box):
* lisp.h (struct ephemeron):
* lisp.h (struct weak_list):
* lrecord.h:
* lrecord.h (struct lrecord_implementation):
* lrecord.h (MC_ALLOC_CALL_FINALIZER):
* lrecord.h (struct lcrecord_list):
* lstream.c (finalize_lstream):
* lstream.c (sizeof_lstream):
* lstream.c (Lstream_new):
* lstream.c (Lstream_delete):
* lstream.h (struct lstream):
* marker.c:
* marker.c (finalize_marker):
* marker.c (compute_buffer_marker_usage):
* mule-charset.c:
* mule-charset.c (make_charset):
* mule-charset.c (compute_charset_usage):
* objects-impl.h (struct Lisp_Color_Instance):
* objects-impl.h (struct Lisp_Font_Instance):
* objects-tty-impl.h (struct tty_color_instance_data):
* objects-tty-impl.h (struct tty_font_instance_data):
* objects-tty.c (tty_initialize_color_instance):
* objects-tty.c (tty_initialize_font_instance):
* objects.c (finalize_color_instance):
* objects.c (Fmake_color_instance):
* objects.c (finalize_font_instance):
* objects.c (Fmake_font_instance):
* objects.c (reinit_vars_of_objects):
* opaque.c:
* opaque.c (sizeof_opaque):
* opaque.c (make_opaque_ptr):
* opaque.c (free_opaque_ptr):
* opaque.h:
* opaque.h (Lisp_Opaque):
* opaque.h (Lisp_Opaque_Ptr):
* print.c (printing_unreadable_lcrecord):
* print.c (external_object_printer):
* print.c (debug_p4):
* process.c (finalize_process):
* process.c (make_process_internal):
* procimpl.h (struct Lisp_Process):
* rangetab.c (Fmake_range_table):
* rangetab.c (Fcopy_range_table):
* rangetab.h (struct Lisp_Range_Table):
* scrollbar.c:
* scrollbar.c (create_scrollbar_instance):
* scrollbar.c (compute_scrollbar_instance_usage):
* scrollbar.h (struct scrollbar_instance):
* specifier.c (finalize_specifier):
* specifier.c (sizeof_specifier):
* specifier.c (set_specifier_caching):
* specifier.h (struct Lisp_Specifier):
* specifier.h (struct specifier_caching):
* symeval.h:
* symeval.h (SYMBOL_VALUE_MAGIC_P):
* symeval.h (DEFVAR_SYMVAL_FWD):
* symsinit.h:
* syntax.c (init_buffer_syntax_cache):
* syntax.h (struct syntax_cache):
* toolbar.c:
* toolbar.c (allocate_toolbar_button):
* toolbar.c (update_toolbar_button):
* toolbar.h (struct toolbar_button):
* tooltalk.c (struct Lisp_Tooltalk_Message):
* tooltalk.c (make_tooltalk_message):
* tooltalk.c (struct Lisp_Tooltalk_Pattern):
* tooltalk.c (make_tooltalk_pattern):
* ui-gtk.c:
* ui-gtk.c (allocate_ffi_data):
* ui-gtk.c (emacs_gtk_object_finalizer):
* ui-gtk.c (allocate_emacs_gtk_object_data):
* ui-gtk.c (allocate_emacs_gtk_boxed_data):
* ui-gtk.h:
* window-impl.h (struct window):
* window-impl.h (struct window_mirror):
* window.c (finalize_window):
* window.c (allocate_window):
* window.c (new_window_mirror):
* window.c (mark_window_as_deleted):
* window.c (make_dummy_parent):
* window.c (compute_window_mirror_usage):
* window.c (compute_window_usage):
Overall point of this change and previous ones in this repository:
(1) Introduce new, clearer terminology: everything other than int
or char is a "record" object, which comes in two types: "normal
objects" and "frob-block objects". Fix up all places that
referred to frob-block objects as "simple", "basic", etc.
(2) Provide an advertised interface for doing operations on Lisp
objects, including creating new types, that is clean and
consistent in its naming, uses the above-referenced terms and
avoids referencing "lrecords", "old lcrecords", etc., which should
hide under the surface.
(3) Make the size_in_bytes and finalizer methods take a
Lisp_Object rather than a void * for consistency with other methods.
(4) Separate finalizer method into finalizer and disksaver, so
that normal finalize methods don't have to worry about disksaving.
Other specifics:
(1) Renaming:
LISP_OBJECT_HEADER -> NORMAL_LISP_OBJECT_HEADER
ALLOC_LISP_OBJECT -> ALLOC_NORMAL_LISP_OBJECT
implementation->basic_p -> implementation->frob_block_p
ALLOCATE_FIXED_TYPE_AND_SET_IMPL -> ALLOC_FROB_BLOCK_LISP_OBJECT
*FCCONFIG*, wrap_fcconfig -> *FC_CONFIG*, wrap_fc_config
*FCPATTERN*, wrap_fcpattern -> *FC_PATTERN*, wrap_fc_pattern
(the last two changes make the naming of these macros consistent
with the naming of all other macros, since the objects are named
fc-config and fc-pattern with a hyphen)
(2) Lots of documentation fixes in lrecord.h.
(3) Eliminate macros for copying, freeing, zeroing objects, getting
their storage size. Instead, new functions:
zero_sized_lisp_object()
zero_nonsized_lisp_object()
lisp_object_storage_size()
free_normal_lisp_object()
(copy_lisp_object() already exists)
LISP_OBJECT_FROB_BLOCK_P() (actually a macro)
Eliminated:
free_lrecord()
zero_lrecord()
copy_lrecord()
copy_sized_lrecord()
old_copy_lcrecord()
old_copy_sized_lcrecord()
old_zero_lcrecord()
old_zero_sized_lcrecord()
LISP_OBJECT_STORAGE_SIZE()
COPY_SIZED_LISP_OBJECT()
COPY_SIZED_LCRECORD()
COPY_LISP_OBJECT()
ZERO_LISP_OBJECT()
FREE_LISP_OBJECT()
(4) Catch the remaining places where lrecord stuff was used directly
and use the advertised interface, e.g. alloc_sized_lrecord() ->
ALLOC_SIZED_LISP_OBJECT().
(5) Make certain statically-declared pseudo-objects
(buffer_local_flags, console_local_flags) have their lheader
initialized correctly, so things like copy_lisp_object() can work
on them. Make extent_auxiliary_defaults a proper heap object
Vextent_auxiliary_defaults, and make extent auxiliaries dumpable
so that this object can be dumped. allocate_extent_auxiliary()
now just creates the object, and attach_extent_auxiliary()
creates an extent auxiliary and attaches to an extent, like the
old allocate_extent_auxiliary().
(6) Create EXTENT_AUXILIARY_SLOTS macro, similar to the foo-slots.h
files but in a macro instead of a file. The purpose is to avoid
duplication when iterating over all the slots in an extent auxiliary.
Use it.
(7) In lstream.c, don't zero out object after allocation because
allocation routines take care of this.
(8) In marker.c, fix a mistake in computing marker overhead.
(9) In print.c, clean up printing_unreadable_lcrecord(),
external_object_printer() to avoid lots of ifdef NEW_GC's.
(10) Separate toolbar-button allocation into a separate
allocate_toolbar_button() function for use in the example code
in lrecord.h.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Mar 2010 04:08:17 -0600 |
parents | 854c88538753 |
children | 308d34e9f07d |
line wrap: on
line source
/* ellcc.c - front-end for compiling Emacs modules Copyright (C) 1998, 1999 J. Kean Johnston. Copyright (C) 2002 Jerry James. This file is part of XEmacs. XEmacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. XEmacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with XEmacs; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Author: J. Kean Johnston (jkj@sco.com). Please mail bugs and suggestions to the XEmacs maintainer. */ /* Here's the scoop. We would really like this to be a shell script, but the various Windows platforms don't have reliable scripting that suits our needs. We don't want to rely on perl or some other such language so we have to roll our own executable to act as a front-end for the compiler. This program is used to invoke the compiler, the linker and to generate the module specific documentation and initialization code. We assume we are in 'compile' mode unless we encounter an argument which tells us that we're not. We take all arguments and pass them on directly to the compiler, except for a few which are specific to this program: --mode=VALUE This sets the program mode. VALUE can be one of compile, link, init or verbose. --mod-name=NAME Sets the module name to the string NAME. --mod-title=TITLE Sets the module title to the string TITLE. --mod-version=VER Sets the module version to the string VER. The idea is that Makefiles will use ellcc as the compiler for making dynamic Emacs modules, and life should be as simple as: make CC=ellcc LD='ellcc --mode=link' The only additional requirement is an entry in the Makefile to produce the module initialization file, which will usually be something along the lines of: modinit.c: $(SRCS) ellcc --mode=init --mod-name=\"$(MODNAME)\" \ --mod-title=\"$(MODTITLE)\" --mod-version=\"$(MODVERSION)\" \ -o $@ $(SRCS) See the samples for more details. */ #include <config.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <sys/types.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif /* HAVE_UNISTD_H */ #define EMODULES_GATHER_VERSION #define EXEC_GROW_SIZE 4 #include <emodules.h> #include <ellcc.h> /* Generated files must be included using <...> */ #include "compiler.h" #ifndef HAVE_SHLIB int main (int argc, char *argv[]) { fprintf (stderr, "Dynamic modules not supported on this platform\n"); return EXIT_FAILURE; } #else /* * Try to figure out the commands we need to use to create shared objects, * and how to compile for PIC mode. */ static char *progname; static char *mod_name = NULL; static char *mod_version = NULL; static char *mod_title = NULL; static char *mod_output = NULL; static int exec_argc = 1; static int exec_length = 0; static int *exec_args; static int real_argc = 0; static char **prog_argv; /* * We allow the user to override things in the environment */ static char *ellcc, *ellld, *ellcflags, *ellldflags, *ellpicflags, *elldllflags; #define OVERENV(STR,EVAR,DFLT) \ do { \ STR = getenv (EVAR); \ if ((STR) == NULL) { \ STR = DFLT; \ } \ } while(0) /* * xnew, xrnew -- allocate, reallocate storage * * SYNOPSIS: Type *xnew (int n, Type); * Type *xrnew (OldPointer, int n, Type); */ #ifdef chkmalloc # include "chkmalloc.h" # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \ (n) * sizeof (Type))) # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \ (op), (n) * sizeof (Type))) #else # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type))) #endif /* * Ellcc modes of operation */ enum mode { ELLCC_COMPILE_MODE, ELLCC_LINK_MODE, ELLCC_INIT_MODE }; #ifdef DEBUG static const char *ellcc_mode_name (enum mode ellcc_mode) ATTRIBUTE_CONST; static const char * ellcc_mode_name (enum mode ellcc_mode) { switch (ellcc_mode) { case ELLCC_COMPILE_MODE: return "compile"; case ELLCC_LINK_MODE: return "link"; case ELLCC_INIT_MODE: return "init"; } return ""; } #endif /* * Function Prototypes */ static void *xmalloc (size_t size) ATTRIBUTE_MALLOC; static void *xrealloc (void *ptr, size_t size) ATTRIBUTE_MALLOC; static char *xstrdup (char *) ATTRIBUTE_MALLOC; static DECLARE_DOESNT_RETURN (fatal (char *, ...)) PRINTF_ARGS (1, 2); static char ** add_string (char **, char *); static char ** add_to_argv (char **, const char *); static char ** do_compile_mode (void); static char ** do_link_mode (void); static char ** do_init_mode (void); #define SSTR(S) ((S) != NULL ? (S) : "") int main (int argc, char *argv[]) { char *tmp; char ** exec_argv; int i, done_mode = 0, verbose = 0; enum mode ellcc_mode; if (argc < 2) { /* FIXME: Print usage output instead */ fatal ("too few arguments"); } prog_argv = argv; #if defined(WIN32_NATIVE) tmp = strrchr (argv[0], '\\'); if (tmp != NULL) { tmp++; } #elif !defined (VMS) tmp = strrchr (argv[0], '/'); if (tmp != NULL) { tmp++; } #else tmp = argv[0]; #endif progname = (tmp == NULL) ? argv[0] : tmp; tmp = &progname[strlen(progname)-2]; if (strcmp (tmp, "cc") == 0) { ellcc_mode = ELLCC_COMPILE_MODE; } else if (strcmp (tmp, "ld") == 0) { ellcc_mode = ELLCC_LINK_MODE; } else if (strcmp (tmp, "it") == 0) { ellcc_mode = ELLCC_INIT_MODE; } else { ellcc_mode = ELLCC_COMPILE_MODE; } exec_args = xnew(argc, int); exec_args[0] = 0; for (i = 1; i < argc; i++) { exec_args[i] = -1; } for (i = 1; i < argc; i++) { if (strncmp (argv[i], "--mode=", (size_t)7) == 0) { char *modeopt = &argv[i][7]; if (done_mode && strcmp (modeopt, "verbose") != 0) { fatal ("more than one mode specified"); } if (strcmp (modeopt, "link") == 0) { done_mode++; ellcc_mode = ELLCC_LINK_MODE; } else if (strcmp (modeopt, "compile") == 0) { done_mode++; ellcc_mode = ELLCC_COMPILE_MODE; } else if (strcmp (modeopt, "init") == 0) { done_mode++; ellcc_mode = ELLCC_INIT_MODE; } else if (strcmp (modeopt, "verbose") == 0) { verbose++; } else { fatal ("Mode must be link, compile, init, or verbose"); } } else if (strcmp (argv[i], "--mod-location") == 0) { printf ("%s\n", ELLCC_MODDIR); exit (EXIT_SUCCESS); } else if (strcmp (argv[i], "--mod-site-location") == 0) { printf ("%s\n", ELLCC_SITEMODS); exit (EXIT_SUCCESS); } else if (strcmp (argv[i], "--mod-archdir") == 0) { printf ("%s\n", ELLCC_ARCHDIR); exit (EXIT_SUCCESS); } else if (strcmp (argv[i], "--mod-config") == 0) { printf ("%s\n", ELLCC_CONFIG); exit (EXIT_SUCCESS); } else if (strncmp (argv[i], "--mod-name=", (size_t)11) == 0) { mod_name = &argv[i][11]; } else if (strncmp (argv[i], "--mod-title=", (size_t)12) == 0) { mod_title = &argv[i][12]; } else if (strncmp (argv[i], "--mod-version=", (size_t)14) == 0) { mod_version = &argv[i][14]; } else if (strncmp (argv[i], "--mod-output=", (size_t)13) == 0) { mod_output = &argv[i][13]; } else { exec_args[exec_argc] = i; exec_argc++; } } if (ellcc_mode == ELLCC_LINK_MODE && mod_output == NULL) { fatal ("must specify --mod-output when linking"); } if (ellcc_mode == ELLCC_INIT_MODE && mod_output == NULL) { fatal ("must specify --mod-output when creating init file"); } if (ellcc_mode == ELLCC_INIT_MODE && mod_name == NULL) { fatal ("must specify --mod-name when creating init file"); } /* * We now have the list of arguments to pass to the compiler or * linker (or to process for doc files). We can do the real work now. */ if (verbose) { printf ("ellcc driver version %s for EMODULES version %s (%ld)\n", ELLCC_EMACS_VER, EMODULES_VERSION, EMODULES_REVISION); } #ifdef DEBUG if (verbose >= 2) { printf (" mode = %d (%s)\n", (int)ellcc_mode, ellcc_mode_name (ellcc_mode)); printf (" module_name = \"%s\"\n", SSTR(mod_name)); printf (" module_title = \"%s\"\n", SSTR(mod_title)); printf (" module_version = \"%s\"\n", SSTR(mod_version)); printf (" CC = %s\n", ELLCC_CC); printf (" CFLAGS = %s\n", ELLCC_CFLAGS); printf (" CC PIC flags = %s\n", ELLCC_DLL_CFLAGS); printf (" LD = %s\n", ELLCC_DLL_LD); printf (" LDFLAGS = %s\n", ELLCC_DLL_LDFLAGS); printf (" architecture = %s\n", ELLCC_CONFIG); printf (" Include directory = %s/include\n", ELLCC_ARCHDIR); printf ("\n"); } #endif if (exec_argc < 2) { /* FIXME: Print usage output instead */ fatal ("too few arguments"); } /* * Get the overrides from the environment */ OVERENV(ellcc, "ELLCC", ELLCC_CC); OVERENV(ellld, "ELLLD", ELLCC_DLL_LD); OVERENV(ellcflags, "ELLCFLAGS", ELLCC_CFLAGS); OVERENV(ellldflags, "ELLLDFLAGS", ELLCC_LDFLAGS); OVERENV(elldllflags, "ELLDLLFLAGS", ELLCC_DLL_LDFLAGS); OVERENV(ellpicflags, "ELLPICFLAGS", ELLCC_DLL_CFLAGS); switch (ellcc_mode) { case ELLCC_COMPILE_MODE: exec_argv = do_compile_mode (); break; case ELLCC_LINK_MODE: exec_argv = do_link_mode (); break; default: exec_argv = do_init_mode (); break; } /* * The arguments to pass on to the desired program have now been set * up and we can run the program. */ if (verbose) { for (i = 0; i < real_argc; i++) { printf ("%s ", exec_argv[i]); } printf ("\n"); (void)fflush (stdout); } /* Terminate argument list. */ exec_argv = add_string (exec_argv, NULL); i = execvp (exec_argv[0], exec_argv); if (verbose) { printf ("%s exited with status %d\n", exec_argv[0], i); } exit (i); } /* Like malloc but get fatal error if memory is exhausted. */ static void * xmalloc (size_t size) { void *result = malloc (size); if (result == NULL) { fatal ("virtual memory exhausted"); } return result; } /* Like realloc but get fatal error if memory is exhausted. */ static void * xrealloc (void *ptr, size_t size) { void *result = realloc (ptr, size); if (result == NULL) { fatal ("virtual memory exhausted"); } return result; } /* Like strdup but get fatal error if memory is exhausted. */ static char * xstrdup (char *s) { char *result = strdup (s); if (result == NULL) { fatal ("virtual memory exhausted"); } return result; } /* Print error message and exit. */ static DOESNT_RETURN fatal (char *format, ...) { va_list ap; va_start (ap, format); (void)fprintf (stderr, "%s: ", progname); (void)vfprintf (stderr, format, ap); (void)fprintf (stderr, "\n"); va_end (ap); exit (EXIT_FAILURE); } static char ** add_string (char **exec_argv, char *str) { if (real_argc >= exec_length) { exec_length = real_argc + EXEC_GROW_SIZE; exec_argv = xrnew (exec_argv, exec_length, char *); } exec_argv[real_argc++] = str; return exec_argv; } /* * Add a string to the argument vector list that will be passed on down * to the compiler or linker. We need to split individual words into * arguments, taking quoting into account. */ static char ** add_to_argv (char **exec_argv, const char *str) { /* Don't add nonexistent strings */ if (str == NULL) { return exec_argv; } /* Skip leading whitespace */ while (isspace (*str)) { str++; } /* Don't add nonexistent strings */ if (*str == '\0') { return exec_argv; } while (*str != '\0') { const char *s; char *arg; int l; s = str; /* Mark the start of THIS argument */ /* Find contiguous nonwhitespace characters */ while (*str != '\0' && !isspace(*str)) { if (*str == '\\') /* Escaped character */ { str++; if (*str != '\0') { str++; } } else if (*str == '\'') { str++; while (*str != '\0' && *str != '\'') { if (str[0] == '\\' && str[1] != '\0') { str += 2; } else { str++; } } if (*str == '\'') { str++; } } else if (*str == '\"') { str++; while (*str != '\0' && *str != '\"') { if (str[0] == '\\' && str[1] != '\0') { str += 2; } else { str++; } } if (*str == '\"') { str++; } } else { str++; /* Normal character. Advance the pointer. */ } } /* Reached the end of the argument. Add it. */ l = str-s; arg = xnew(l+1, char); strncpy(arg, s, (size_t)l); arg[l] = '\0'; exec_argv = add_string (exec_argv, arg); /* Skip trailing whitespace */ while (isspace (*str)) { str++; } } return exec_argv; } /* * For compile mode, things are pretty straight forward. All we need to do * is build up the argument vector and exec() it. We must just make sure * that we get all of the required arguments in place. */ static char ** do_compile_mode (void) { int i; char **exec_argv = xnew (exec_argc + 20, char *); exec_argv = add_to_argv (exec_argv, ellcc); exec_argv = add_to_argv (exec_argv, ELLCC_CF_ALL); exec_argv = add_to_argv (exec_argv, ellcflags); exec_argv = add_to_argv (exec_argv, ellpicflags); exec_argv = add_to_argv (exec_argv, "-DPIC"); exec_argv = add_to_argv (exec_argv, "-DEMACS_MODULE"); #ifdef XEMACS /* Cover both cases */ exec_argv = add_to_argv (exec_argv, "-DXEMACS_MODULE"); exec_argv = add_to_argv (exec_argv, "-Dxemacs"); #endif exec_argv = add_to_argv (exec_argv, "-Demacs"); for (i = 1; i < exec_argc; i++) { exec_argv = add_string (exec_argv, xstrdup (prog_argv[exec_args[i]])); } return exec_argv; } /* * For link mode, things are a little bit more complicated. We need to * insert the linker commands first, replace any occurrence of ELLSONAME * with the desired output file name, insert the output arguments, then * all of the provided arguments, then the final post arguments. Once * all of this has been done, the argument vector is ready to run. */ static char ** do_link_mode (void) { int i,x; char *t, *ts; char **exec_argv = xnew(exec_argc + 10, char *); exec_argv = add_to_argv (exec_argv, ellld); exec_argv = add_to_argv (exec_argv, ellldflags); exec_argv = add_to_argv (exec_argv, elldllflags); exec_argv = add_to_argv (exec_argv, ELLCC_DLL_LDO); exec_argv = add_to_argv (exec_argv, mod_output); for (i = 1; i < exec_argc; i++) { exec_argv = add_string (exec_argv, xstrdup (prog_argv[exec_args[i]])); } exec_argv = add_to_argv (exec_argv, ELLCC_DLL_POST); /* * Now go through each argument and replace ELLSONAME with mod_output. */ for (i = 0; i < real_argc; i++) { x = 0; ts = xnew (2 * strlen (exec_argv[i]), char); ts[0] = '\0'; t = exec_argv[i]; while (*t != '\0') { if (*t == 'E') { if (strncmp (t, "ELLSONAME", (size_t)9) == 0) { strcat (ts, mod_output); x += strlen (mod_output); t += 8; } else { ts[x] = *t; x++; ts[x] = '\0'; } } else { ts[x] = *t; x++; ts[x] = '\0'; } t++; } free (exec_argv[i]); exec_argv[i] = ts; } return exec_argv; } /* * In init mode, things are a bit easier. We assume that the only things * passed on the command line are the names of source files which the * make-doc program will be processing. We prepare the output file with * the header information first, as make-doc will append to the file by * special dispensation. */ static char ** do_init_mode (void) { int i; char *ts, *mdocprog; char **exec_argv = xnew(exec_argc + 8, char *); FILE *mout = fopen (mod_output, "w"); if (mout == NULL) { fatal ("Failed to open output file %s", mod_output); } fprintf (mout, "/* DO NOT EDIT - AUTOMATICALLY GENERATED */\n\n"); fprintf (mout, "#include <emodules.h>\n\n"); fprintf (mout, "#ifdef __cplusplus\n"); fprintf (mout, "extern \"C\" {\n"); fprintf (mout, "#endif\n"); fprintf (mout, "extern const long emodule_compiler;\n"); fprintf (mout, "extern const char *emodule_name, *emodule_version, *emodule_title;\n"); fprintf (mout, "extern void docs_of_%s (void);\n", SSTR(mod_name)); fprintf (mout, "#ifdef __cplusplus\n"); fprintf (mout, "}\n"); fprintf (mout, "#endif\n\n"); fprintf (mout, "const long emodule_compiler = %ld;\n", EMODULES_REVISION); fprintf (mout, "const char *emodule_name = \"%s\";\n", SSTR(mod_name)); fprintf (mout, "const char *emodule_version = \"%s\";\n", SSTR(mod_version)); fprintf (mout, "const char *emodule_title = \"%s\";\n\n", SSTR(mod_title)); fprintf (mout, "void docs_of_%s ()\n", SSTR(mod_name)); if (fclose (mout) != 0) { fatal ("Failed to close output file %s", mod_output); } mdocprog = getenv ("ELLMAKEDOC"); if (mdocprog == NULL) { mdocprog = xnew (14 + strlen (ELLCC_ARCHDIR), char); sprintf (mdocprog, "%s/make-docfile", ELLCC_ARCHDIR); exec_argv = add_to_argv (exec_argv, mdocprog); free (mdocprog); } else { exec_argv = add_to_argv (exec_argv, mdocprog); } ts = xnew (4 + strlen (mod_output), char); sprintf (ts, "-E %s", mod_output); exec_argv = add_to_argv (exec_argv, ts); free (ts); for (i = 1; i < exec_argc; i++) { exec_argv = add_string (exec_argv, xstrdup (prog_argv[exec_args[i]])); } return exec_argv; } #endif /* HAVE_SHLIB */