Mercurial > hg > xemacs-beta
annotate src/doprnt.c @ 1204:e22b0213b713
[xemacs-hg @ 2003-01-12 11:07:58 by michaels]
modules/ChangeLog:
2002-12-16 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c:
remove ifdef USE_KKCC.
src/ChangeLog:
2003-01-08 Mike Sperber <mike@xemacs.org>
* console.h (CDFW_CONSOLE): Don't lead to a crash if we're dealing
with a dead window/frame/device/console.
2002-12-20 Mike Sperber <mike@xemacs.org>
* ui-gtk.c: Fix typo from Ben's patch: emacs_ffi_data is a
typedef, not a struct. emacs_gtk_object_data is a typedef, not a
struct.
* gtk-glue.c (gdk_event_to_emacs_event): Fix typos from Ben's
patch: le -> emacs_event + rearrange the code.
* event-gtk.c (gtk_event_to_emacs_event): Fix typos from Ben's
patch: ..._UNDERLYING_GDK_EVENT -> ..._GDK_EVENT, ev -> key_event.
* device-gtk.c: Fix typo from Ben's patch: x_keysym_map_hash_table
-> x_keysym_map_hashtable.
2002-12-19 Mike Sperber <mike@xemacs.org>
* menubar-x.c (set_frame_menubar): Initialize protect_me field of
popup_data.
2002-12-16 Ben Wing <ben@xemacs.org>
Major cleanup of KKCC, etc.
KKCC, pdump-related:
-- descriptions are written for all objects. this required some
changes in the format of some objects, e.g. extents, popup-data,
coding system, lstream, lcrecord-list.
-- KKCC now handles weakness in markers, hash tables, elsewhere
correctly (formerly, you'd eventually get a stack overflow due
to endlessly expanding markers).
-- textual changes: lrecord_description -> memory_description,
struct_description -> sized_memory_description.
-- extensive comment describing descriptions and pdump.
-- redo XD_UNION so it works inline and change its format to provide
sufficient info for pdump. implement XD_UNION in pdump. also add
XD_UNION_DYNAMIC_SIZE, which works like XD_UNION except for when
auto-computing structure sizes.
-- add support for XD_INDIRECT in description offsets (used by
extents).
-- add support for "description maps", allowing for indirect
descriptions that are retrieved from an object at run-time. this
generalizes XD_CODING_SYSTEM_END, XD_SPECIFIER_END, etc., which
have now been eliminated.
-- add a fifth field "flags" to memory_description, to support flags
that can be specified for this particular line. Currently defined
flags are XD_FLAG_NO_KKCC (KKCC should ignore this entry; useful
for the weakness above in markers, etc.), XD_FLAG_NO_PDUMP (pdump
should ignore this entry), XD_FLAG_UNION_DEFAULT_ENTRY (in
union maps, this specifies a "default" entry for all remaining
values), and XD_FLAG_FREE_LISP_OBJECT (for use with lcrecord-lists).
-- clean up the kkcc-itis in events, so that the differences
between event data as separate objects and as a union are now
minimized to a small number of places. with the new XD_UNION, we
no longer need event data as separate objects, so this code is no
longer ifdef USE_KKCC, but instead ifdef EVENT_DATA_AS_OBJECTS,
not used by default. make sure that we explicitly free the
separate event data objects when no longer in use, to maintain the
invariant the event processing causes no consing.
-- also remove other USE_KKCC ifdefs when not necessary.
-- allow for KKCC compilation under MS Windows.
-- fix README.kkcc.
-- dump_add_root_object -> dump_add_root_lisp_object.
-- implement dump_add_root_block and use this to handle
dump_add_opaque.
-- factor out some code duplicated in kkcc and pdump.
Other allocation/object-related:
-- change various *slots.h so MARKED_SLOT() call no longer
includes semicolon.
-- free_marker() takes a Lisp_Object not a direct pointer.
-- make bit vectors lcrecords, like vectors, and eliminate code
that essentially duplicated the lcrecord handling.
-- additional asserts in FREE_FIXED_TYPE, formerly duplicated in
the various callers of this.
-- all lcrecord allocation functions now zero out the returned
lcrecords. unnecessary calls to zero_lcrecord removed. add long
comment describing these functions.
-- extract out process and coding system slots, like for buffers,
frames, etc.
-- lcrecords now set the type of items sitting on the free list to
lcrecord_type_free.
-- changes to the way that gap arrays are allocated, for kkcc's
benefit -- now, one single memory block with a stretchy array on
the end, instead of a separate block holding the array.
Error-checking-related:
-- now can compile with C++ under MS Windows. clean up compile errors
discovered that way. (a few were real problems)
-- add C++ error-checking code to verify problems with mismatched
GCPRO/UNGCPRO. (there were a few in the kkcc code.) add long
comment about how to catch insufficient GCPRO (yes, it's possible
using C++).
-- add debug_p4(), a simple object printer, when debug_print()
doesn't work.
-- add dp() and db() as short synonyms of debug_print(),
debug_backtrace().
-- `print' tries EXTREMELY hard to avoid core dumping when printing
when crashing or from debug_print(), and tries as hard as it
reasonably can in other situations.
-- Correct the message output upon crashing to be more up-to-date.
Event-related:
-- document event-matches-key-specifier-p better.
-- generalize the dispatch queues formerly duplicated in the
various event implementations. add event methods to drain pending
events. generalize and clean up QUIT handling, removing
event-specific quit processing. allow arbitrary keystrokes, not
just ASCII, to be the QUIT char. among other things, this should
fix some longstanding bugs in X quit handling. long comment
describing the various event queues.
-- implement delaying of XFlush() if there are pending expose events.
SOMEONE PLEASE TRY THIS OUT.
-- Fix `xemacs -batch -l dunnet' under Cygwin. Try to fix under
MS Windows but not quite there yet.
Other:
-- class -> class_ and no more C++ games with this item.
new -> new_ in the lwlib code, so far not elsewhere.
-- use `struct htentry' not `struct hentry' in elhash.c to avoid
debugger confusion with hash.c.
-- new macros ALIST_LOOP_3, ALIST_LOOP_4.
* README.kkcc:
* alloc.c:
* alloc.c (deadbeef_memory):
* alloc.c (allocate_lisp_storage):
* alloc.c (copy_lisp_object):
* alloc.c (ALLOCATE_FIXED_TYPE_1):
* alloc.c (FREE_FIXED_TYPE):
* alloc.c (make_vector_internal):
* alloc.c (make_bit_vector_internal):
* 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 (struct string_chars_block):
* alloc.c (mark_lcrecord_list):
* alloc.c (make_lcrecord_list):
* alloc.c (alloc_managed_lcrecord):
* alloc.c (free_managed_lcrecord):
* alloc.c (alloc_automanaged_lcrecord):
* alloc.c (staticpro_1):
* alloc.c (staticpro):
* alloc.c (lispdesc_indirect_count_1):
* alloc.c (lispdesc_indirect_description_1):
* alloc.c (lispdesc_one_description_line_size):
* alloc.c (lispdesc_structure_size):
* alloc.c (mark_object_maybe_checking_free):
* alloc.c (mark_with_description):
* alloc.c (mark_struct_contents):
* alloc.c (mark_object):
* alloc.c (tick_lcrecord_stats):
* alloc.c (free_cons):
* alloc.c (free_key_data):
* alloc.c (free_button_data):
* alloc.c (free_motion_data):
* alloc.c (free_process_data):
* alloc.c (free_timeout_data):
* alloc.c (free_magic_data):
* alloc.c (free_magic_eval_data):
* alloc.c (free_eval_data):
* alloc.c (free_misc_user_data):
* alloc.c (free_marker):
* alloc.c (compact_string_chars):
* alloc.c (gc_sweep):
* alloc.c (garbage_collect_1):
* alloc.c (Fgarbage_collect):
* alloc.c (common_init_alloc_early):
* alloc.c (init_alloc_early):
* alloc.c (init_alloc_once_early):
* buffer.c:
* buffer.c (mark_buffer):
* buffer.c (MARKED_SLOT):
* buffer.c (cleanup_buffer_undo_lists):
* buffer.c (Fget_file_buffer):
* buffer.h (MARKED_SLOT):
* bufslots.h:
* bytecode.c:
* callint.c:
* casetab.c:
* chartab.c:
* chartab.c (symbol_to_char_table_type):
* cmdloop.c:
* cmdloop.c (Fcommand_loop_1):
* config.h.in (new):
* conslots.h:
* console-gtk-impl.h (struct gtk_frame):
* console-impl.h:
* console-impl.h (struct console):
* console-impl.h (MARKED_SLOT):
* console-impl.h (CONSOLE_QUIT_EVENT):
* console-msw-impl.h (XM_BUMPQUEUE):
* console-msw.c (write_string_to_mswindows_debugging_output):
* console-msw.h:
* console-stream-impl.h:
* console-stream-impl.h (struct stream_console):
* console-stream.c:
* console-stream.c (stream_init_console):
* console-stream.h:
* console-tty.c:
* console-tty.h:
* console-x.h:
* console.c:
* console.c (mark_console):
* console.c (MARKED_SLOT):
* console.c (allocate_console):
* console.c (get_console_variant):
* console.c (create_console):
* console.c (delete_console_internal):
* console.c (Fset_input_mode):
* console.c (Fcurrent_input_mode):
* console.c (common_init_complex_vars_of_console):
* console.h:
* console.h (console_variant):
* console.h (device_metrics):
* data.c:
* data.c (Faref):
* data.c (Faset):
* data.c (decode_weak_list_type):
* database.c:
* debug.c (xemacs_debug_loop):
* debug.c (FROB):
* debug.c (Fadd_debug_class_to_check):
* debug.c (Fdelete_debug_class_to_check):
* debug.c (Fset_debug_classes_to_check):
* debug.c (Fset_debug_class_types_to_check):
* debug.c (Fdebug_types_being_checked):
* debug.h (DASSERT):
* device-gtk.c:
* device-impl.h (struct device):
* device-impl.h (MARKED_SLOT):
* device-msw.c:
* device-x.c:
* device-x.c (x_init_device_class):
* device-x.c (x_comp_visual_info):
* device-x.c (x_try_best_visual_class):
* device-x.c (x_init_device):
* device-x.c (construct_name_list):
* device-x.c (x_get_resource_prefix):
* device-x.c (Fx_get_resource):
* device-x.c (Fx_display_visual_class):
* device.c:
* device.c (MARKED_SLOT):
* device.c (allocate_device):
* device.c (Fmake_device):
* device.c (delete_device_internal):
* device.c (Fset_device_class):
* device.h:
* devslots.h:
* devslots.h (MARKED_SLOT):
* dialog-msw.c:
* dired-msw.c (mswindows_ls_sort_fcn):
* dired-msw.c (mswindows_get_files):
* dired-msw.c (mswindows_format_file):
* doprnt.c (parse_doprnt_spec):
* dumper.c:
* dumper.c (struct):
* dumper.c (dump_add_root_block):
* dumper.c (dump_add_root_struct_ptr):
* dumper.c (dump_add_root_lisp_object):
* dumper.c (pdump_struct_list_elt):
* dumper.c (pdump_get_entry_list):
* dumper.c (pdump_backtrace):
* dumper.c (pdump_bump_depth):
* dumper.c (pdump_register_sub):
* dumper.c (pdump_register_object):
* dumper.c (pdump_register_struct_contents):
* dumper.c (pdump_register_struct):
* dumper.c (pdump_store_new_pointer_offsets):
* dumper.c (pdump_dump_data):
* dumper.c (pdump_reloc_one):
* dumper.c (pdump_allocate_offset):
* dumper.c (pdump_scan_by_alignment):
* dumper.c (pdump_dump_root_blocks):
* dumper.c (pdump_dump_rtables):
* dumper.c (pdump_dump_root_lisp_objects):
* dumper.c (pdump):
* dumper.c (pdump_load_finish):
* dumper.c (pdump_file_get):
* dumper.c (pdump_resource_get):
* dumper.c (pdump_load):
* editfns.c (save_excursion_restore):
* editfns.c (user_login_name):
* editfns.c (save_restriction_restore):
* elhash.c:
* elhash.c (htentry):
* elhash.c (struct Lisp_Hash_Table):
* elhash.c (HTENTRY_CLEAR_P):
* elhash.c (LINEAR_PROBING_LOOP):
* elhash.c (check_hash_table_invariants):
* elhash.c (mark_hash_table):
* elhash.c (hash_table_equal):
* elhash.c (print_hash_table_data):
* elhash.c (free_hentries):
* elhash.c (make_general_lisp_hash_table):
* elhash.c (decode_hash_table_weakness):
* elhash.c (decode_hash_table_test):
* elhash.c (Fcopy_hash_table):
* elhash.c (resize_hash_table):
* elhash.c (pdump_reorganize_hash_table):
* elhash.c (find_htentry):
* elhash.c (Fgethash):
* elhash.c (Fputhash):
* elhash.c (remhash_1):
* elhash.c (Fremhash):
* elhash.c (Fclrhash):
* elhash.c (copy_compress_hentries):
* elhash.c (elisp_maphash_unsafe):
* elhash.c (finish_marking_weak_hash_tables):
* elhash.c (prune_weak_hash_tables):
* elhash.h:
* emacs.c:
* emacs.c (main_1):
* emacs.c (main):
* emacs.c (shut_down_emacs):
* emodules.h (dump_add_root_lisp_object):
* eval.c:
* eval.c (unwind_to_catch):
* eval.c (maybe_signal_error_1):
* eval.c (maybe_signal_continuable_error_1):
* eval.c (maybe_signal_error):
* eval.c (maybe_signal_continuable_error):
* eval.c (maybe_signal_error_2):
* eval.c (maybe_signal_continuable_error_2):
* eval.c (maybe_signal_ferror):
* eval.c (maybe_signal_continuable_ferror):
* eval.c (maybe_signal_ferror_with_frob):
* eval.c (maybe_signal_continuable_ferror_with_frob):
* eval.c (maybe_syntax_error):
* eval.c (maybe_sferror):
* eval.c (maybe_invalid_argument):
* eval.c (maybe_invalid_constant):
* eval.c (maybe_invalid_operation):
* eval.c (maybe_invalid_change):
* eval.c (maybe_invalid_state):
* eval.c (Feval):
* eval.c (call_trapping_problems):
* eval.c (call_with_suspended_errors):
* eval.c (warn_when_safe_lispobj):
* eval.c (warn_when_safe):
* eval.c (vars_of_eval):
* event-Xt.c:
* event-Xt.c (maybe_define_x_key_as_self_inserting_character):
* event-Xt.c (x_to_emacs_keysym):
* event-Xt.c (x_event_to_emacs_event):
* event-Xt.c (emacs_Xt_enqueue_focus_event):
* event-Xt.c (emacs_Xt_format_magic_event):
* event-Xt.c (emacs_Xt_compare_magic_event):
* event-Xt.c (emacs_Xt_hash_magic_event):
* event-Xt.c (emacs_Xt_handle_magic_event):
* event-Xt.c (Xt_timeout_to_emacs_event):
* event-Xt.c (Xt_process_to_emacs_event):
* event-Xt.c (signal_special_Xt_user_event):
* event-Xt.c (emacs_Xt_next_event):
* event-Xt.c (emacs_Xt_event_handler):
* event-Xt.c (emacs_Xt_drain_queue):
* event-Xt.c (emacs_Xt_event_pending_p):
* event-Xt.c (check_if_pending_expose_event):
* event-Xt.c (reinit_vars_of_event_Xt):
* event-Xt.c (vars_of_event_Xt):
* event-gtk.c:
* event-gtk.c (IS_MODIFIER_KEY):
* event-gtk.c (emacs_gtk_format_magic_event):
* event-gtk.c (emacs_gtk_compare_magic_event):
* event-gtk.c (emacs_gtk_hash_magic_event):
* event-gtk.c (emacs_gtk_handle_magic_event):
* event-gtk.c (gtk_to_emacs_keysym):
* event-gtk.c (gtk_timeout_to_emacs_event):
* event-gtk.c (gtk_process_to_emacs_event):
* event-gtk.c (dragndrop_data_received):
* event-gtk.c (signal_special_gtk_user_event):
* event-gtk.c (emacs_gtk_next_event):
* event-gtk.c (gtk_event_to_emacs_event):
* event-gtk.c (generic_event_handler):
* event-gtk.c (emacs_shell_event_handler):
* event-gtk.c (emacs_gtk_drain_queue):
* event-gtk.c (emacs_gtk_event_pending_p):
* event-gtk.c (reinit_vars_of_event_gtk):
* event-gtk.c (vars_of_event_gtk):
* event-msw.c:
* event-msw.c (struct winsock_stream):
* event-msw.c (winsock_reader):
* event-msw.c (winsock_writer):
* event-msw.c (mswindows_enqueue_dispatch_event):
* event-msw.c (mswindows_enqueue_misc_user_event):
* event-msw.c (mswindows_enqueue_magic_event):
* event-msw.c (mswindows_enqueue_process_event):
* event-msw.c (mswindows_enqueue_mouse_button_event):
* event-msw.c (mswindows_enqueue_keypress_event):
* event-msw.c (mswindows_dequeue_dispatch_event):
* event-msw.c (emacs_mswindows_drain_queue):
* event-msw.c (mswindows_need_event_in_modal_loop):
* event-msw.c (mswindows_need_event):
* event-msw.c (mswindows_wm_timer_callback):
* event-msw.c (dde_eval_string):
* event-msw.c (Fdde_alloc_advise_item):
* event-msw.c (mswindows_dde_callback):
* event-msw.c (mswindows_wnd_proc):
* event-msw.c (remove_timeout_mapper):
* event-msw.c (emacs_mswindows_remove_timeout):
* event-msw.c (emacs_mswindows_event_pending_p):
* event-msw.c (emacs_mswindows_format_magic_event):
* event-msw.c (emacs_mswindows_compare_magic_event):
* event-msw.c (emacs_mswindows_hash_magic_event):
* event-msw.c (emacs_mswindows_handle_magic_event):
* event-msw.c (emacs_mswindows_select_console):
* event-msw.c (emacs_mswindows_unselect_console):
* event-msw.c (reinit_vars_of_event_mswindows):
* event-msw.c (vars_of_event_mswindows):
* event-stream.c:
* event-stream.c (mark_command_builder):
* event-stream.c (reset_command_builder_event_chain):
* event-stream.c (allocate_command_builder):
* event-stream.c (copy_command_builder):
* event-stream.c (command_builder_append_event):
* event-stream.c (event_stream_event_pending_p):
* event-stream.c (event_stream_force_event_pending):
* event-stream.c (maybe_read_quit_event):
* event-stream.c (event_stream_drain_queue):
* event-stream.c (remove_quit_p_event):
* event-stream.c (event_stream_quit_p):
* event-stream.c (echo_key_event):
* event-stream.c (maybe_kbd_translate):
* event-stream.c (execute_help_form):
* event-stream.c (event_stream_generate_wakeup):
* event-stream.c (enqueue_dispatch_event):
* event-stream.c (enqueue_magic_eval_event):
* event-stream.c (Fenqueue_eval_event):
* event-stream.c (enqueue_misc_user_event):
* event-stream.c (enqueue_misc_user_event_pos):
* event-stream.c (next_event_internal):
* event-stream.c (Fnext_event):
* event-stream.c (Faccept_process_output):
* event-stream.c (execute_internal_event):
* event-stream.c (munge_keymap_translate):
* event-stream.c (command_builder_find_leaf_no_mule_processing):
* event-stream.c (command_builder_find_leaf):
* event-stream.c (lookup_command_event):
* event-stream.c (is_scrollbar_event):
* event-stream.c (execute_command_event):
* event-stream.c (Fdispatch_event):
* event-stream.c (Fread_key_sequence):
* event-stream.c (dribble_out_event):
* event-stream.c (vars_of_event_stream):
* event-tty.c (tty_timeout_to_emacs_event):
* event-tty.c (emacs_tty_next_event):
* event-tty.c (emacs_tty_drain_queue):
* event-tty.c (reinit_vars_of_event_tty):
* event-unixoid.c:
* event-unixoid.c (find_tty_or_stream_console_from_fd):
* event-unixoid.c (read_event_from_tty_or_stream_desc):
* event-unixoid.c (drain_tty_devices):
* event-unixoid.c (poll_fds_for_input):
* events.c:
* events.c (deinitialize_event):
* events.c (zero_event):
* events.c (mark_event):
* events.c (print_event_1):
* events.c (print_event):
* events.c (event_equal):
* events.c (event_hash):
* events.c (Fmake_event):
* events.c (Fdeallocate_event):
* events.c (Fcopy_event):
* events.c (map_event_chain_remove):
* events.c (character_to_event):
* events.c (event_to_character):
* events.c (Fevent_to_character):
* events.c (format_event_object):
* events.c (upshift_event):
* events.c (downshift_event):
* events.c (event_upshifted_p):
* events.c (Fevent_live_p):
* events.c (Fevent_type):
* events.c (Fevent_timestamp):
* events.c (CHECK_EVENT_TYPE):
* events.c (CHECK_EVENT_TYPE2):
* events.c (CHECK_EVENT_TYPE3):
* events.c (Fevent_key):
* events.c (Fevent_button):
* events.c (Fevent_modifier_bits):
* events.c (event_x_y_pixel_internal):
* events.c (event_pixel_translation):
* events.c (Fevent_process):
* events.c (Fevent_function):
* events.c (Fevent_object):
* events.c (Fevent_properties):
* events.c (syms_of_events):
* events.c (vars_of_events):
* events.h:
* events.h (struct event_stream):
* events.h (struct Lisp_Key_Data):
* events.h (KEY_DATA_KEYSYM):
* events.h (EVENT_KEY_KEYSYM):
* events.h (struct Lisp_Button_Data):
* events.h (EVENT_BUTTON_BUTTON):
* events.h (struct Lisp_Motion_Data):
* events.h (EVENT_MOTION_X):
* events.h (struct Lisp_Process_Data):
* events.h (EVENT_PROCESS_PROCESS):
* events.h (struct Lisp_Timeout_Data):
* events.h (EVENT_TIMEOUT_INTERVAL_ID):
* events.h (struct Lisp_Eval_Data):
* events.h (EVENT_EVAL_FUNCTION):
* events.h (struct Lisp_Misc_User_Data):
* events.h (EVENT_MISC_USER_FUNCTION):
* events.h (struct Lisp_Magic_Eval_Data):
* events.h (EVENT_MAGIC_EVAL_INTERNAL_FUNCTION):
* events.h (struct Lisp_Magic_Data):
* events.h (EVENT_MAGIC_UNDERLYING):
* events.h (EVENT_MAGIC_GDK_EVENT):
* events.h (struct Lisp_Event):
* events.h (XEVENT_CHANNEL):
* events.h (SET_EVENT_TIMESTAMP_ZERO):
* events.h (SET_EVENT_CHANNEL):
* events.h (SET_EVENT_NEXT):
* events.h (XSET_EVENT_TYPE):
* events.h (struct command_builder):
* extents.c:
* extents.c (gap_array_adjust_markers):
* extents.c (gap_array_recompute_derived_values):
* extents.c (gap_array_move_gap):
* extents.c (gap_array_make_gap):
* extents.c (gap_array_insert_els):
* extents.c (gap_array_delete_els):
* extents.c (gap_array_make_marker):
* extents.c (gap_array_delete_marker):
* extents.c (gap_array_move_marker):
* extents.c (make_gap_array):
* extents.c (free_gap_array):
* extents.c (extent_list_num_els):
* extents.c (extent_list_insert):
* extents.c (mark_extent_auxiliary):
* extents.c (allocate_extent_auxiliary):
* extents.c (decode_extent_at_flag):
* extents.c (verify_extent_mapper):
* extents.c (symbol_to_glyph_layout):
* extents.c (syms_of_extents):
* faces.c:
* file-coding.c:
* file-coding.c (struct_detector_category_description =):
* file-coding.c (detector_category_dynarr_description_1):
* file-coding.c (struct_detector_description =):
* file-coding.c (detector_dynarr_description_1):
* file-coding.c (MARKED_SLOT):
* file-coding.c (mark_coding_system):
* file-coding.c (coding_system_extra_description_map):
* file-coding.c (coding_system_description):
* file-coding.c (allocate_coding_system):
* file-coding.c (symbol_to_eol_type):
* file-coding.c (Fcoding_system_aliasee):
* file-coding.c (set_coding_stream_coding_system):
* file-coding.c (struct convert_eol_coding_system):
* file-coding.c (struct undecided_coding_system):
* file-coding.c (undecided_mark_coding_stream):
* file-coding.c (coding_category_symbol_to_id):
* file-coding.c (struct gzip_coding_system):
* file-coding.c (coding_system_type_create):
* file-coding.h:
* file-coding.h (struct Lisp_Coding_System):
* file-coding.h (CODING_SYSTEM_SLOT_DECLARATION):
* file-coding.h (coding_system_variant):
* file-coding.h (struct coding_system_methods):
* file-coding.h (DEFINE_CODING_SYSTEM_TYPE_WITH_DATA):
* file-coding.h (INITIALIZE_CODING_SYSTEM_TYPE_WITH_DATA):
* file-coding.h (struct coding_stream):
* fileio.c (Fsubstitute_in_file_name):
* floatfns.c:
* fns.c:
* fns.c (base64_encode_1):
* frame-gtk.c:
* frame-gtk.c (Fgtk_start_drag_internal):
* frame-impl.h (struct frame):
* frame-impl.h (MARKED_SLOT):
* frame-msw.c:
* frame-x.c:
* frame-x.c (Fcde_start_drag_internal):
* frame-x.c (Foffix_start_drag_internal):
* frame.c:
* frame.c (MARKED_SLOT):
* frame.c (allocate_frame_core):
* frame.c (delete_frame_internal):
* frame.c (Fmouse_position_as_motion_event):
* frameslots.h:
* frameslots.h (MARKED_SLOT_ARRAY):
* free-hook.c:
* glyphs-msw.c (mswindows_widget_instantiate):
* glyphs-x.c:
* glyphs-x.c (convert_EImage_to_XImage):
* glyphs.c:
* glyphs.c (process_image_string_instantiator):
* glyphs.c (mark_image_instance):
* glyphs.c (allocate_image_instance):
* glyphs.c (unmap_subwindow):
* glyphs.c (map_subwindow):
* glyphs.c (syms_of_glyphs):
* glyphs.c (specifier_type_create_image):
* glyphs.h:
* glyphs.h (struct text_image_instance):
* glyphs.h (struct Lisp_Image_Instance):
* gmalloc.c:
* gmalloc.c ("C"):
* gpmevent.c (Freceive_gpm_event):
* gpmevent.c (gpm_next_event_cb):
* gpmevent.c (vars_of_gpmevent):
* gtk-glue.c (gdk_event_to_emacs_event):
* gtk-xemacs.c (gtk_xemacs_class_init):
* gui-msw.c:
* gui-msw.c (mswindows_handle_gui_wm_command):
* gui-msw.c (mswindows_translate_menu_or_dialog_item):
* gui-x.c:
* gui-x.c (mark_popup_data):
* gui-x.c (snarf_widget_value_mapper):
* gui-x.c (gcpro_popup_callbacks):
* gui-x.c (ungcpro_popup_callbacks):
* gui-x.c (free_popup_widget_value_tree):
* gui-x.c (popup_selection_callback):
* gui-x.h:
* gui-x.h (struct popup_data):
* gui.c:
* gui.c (allocate_gui_item):
* gutter.c (decode_gutter_position):
* hash.c (NULL_ENTRY):
* indent.c (vmotion_1):
* indent.c (vmotion_pixels):
* input-method-motif.c (res):
* input-method-xlib.c (IMInstantiateCallback):
* input-method-xlib.c (XIM_init_device):
* input-method-xlib.c (res):
* intl-encap-win32.c:
* intl-encap-win32.c (qxeSHGetDataFromIDList):
* intl-win32.c:
* intl-win32.c (mswindows_multibyte_cp_type):
* intl-win32.c (struct mswindows_multibyte_coding_system):
* keymap.c:
* keymap.c (make_key_description):
* keymap.c (keymap_store):
* keymap.c (get_keyelt):
* keymap.c (keymap_lookup_1):
* keymap.c (define_key_parser):
* keymap.c (key_desc_list_to_event):
* keymap.c (event_matches_key_specifier_p):
* keymap.c (meta_prefix_char_p):
* keymap.c (ensure_meta_prefix_char_keymapp):
* keymap.c (Fdefine_key):
* keymap.c (struct raw_lookup_key_mapper_closure):
* keymap.c (raw_lookup_key):
* keymap.c (raw_lookup_key_mapper):
* keymap.c (lookup_keys):
* keymap.c (lookup_events):
* keymap.c (Flookup_key):
* keymap.c (struct map_keymap_unsorted_closure):
* keymap.c (map_keymap_unsorted_mapper):
* keymap.c (map_keymap_sorted):
* keymap.c (map_keymap_mapper):
* keymap.c (map_keymap):
* keymap.c (accessible_keymaps_mapper_1):
* keymap.c (Faccessible_keymaps):
* keymap.c (Fsingle_key_description):
* keymap.c (raw_keys_to_keys):
* keymap.c (format_raw_keys):
* keymap.c (where_is_recursive_mapper):
* keymap.c (where_is_internal):
* keymap.c (describe_map_mapper_shadow_search):
* keymap.c (keymap_lookup_inherited_mapper):
* keymap.c (describe_map_mapper):
* keymap.h (event_matches_key_specifier_p):
* lisp.h:
* lisp.h (this):
* lisp.h (RETURN_NOT_REACHED):
* lisp.h (struct Lisp_Vector):
* lisp.h (struct Lisp_Bit_Vector):
* lisp.h (UNGCPRO_1):
* lisp.h (NUNGCPRO):
* lisp.h (NNUNGCPRO):
* lisp.h (DECLARE_INLINE_HEADER):
* lrecord.h:
* lrecord.h (struct lrecord_header):
* lrecord.h (struct lcrecord_header):
* lrecord.h (lrecord_type):
* lrecord.h (struct lrecord_implementation):
* lrecord.h (RECORD_DUMPABLE):
* lrecord.h (memory_description_type):
* lrecord.h (data_description_entry_flags):
* lrecord.h (struct memory_description):
* lrecord.h (struct sized_memory_description):
* lrecord.h (XD_INDIRECT):
* lrecord.h (XD_IS_INDIRECT):
* lrecord.h (XD_DYNARR_DESC):
* lrecord.h (DEFINE_BASIC_LRECORD_IMPLEMENTATION):
* lrecord.h (MAKE_LRECORD_IMPLEMENTATION):
* lrecord.h (MAKE_EXTERNAL_LRECORD_IMPLEMENTATION):
* lrecord.h (alloc_lcrecord_type):
* lstream.c:
* lstream.c (Lstream_new):
* lstream.c (lisp_buffer_marker):
* lstream.h:
* lstream.h (lstream_implementation):
* lstream.h (DEFINE_LSTREAM_IMPLEMENTATION):
* lstream.h (DEFINE_LSTREAM_IMPLEMENTATION_WITH_DATA):
* marker.c:
* marker.c (copy_marker_1):
* mem-limits.h:
* menubar-gtk.c:
* menubar-gtk.c (gtk_popup_menu):
* menubar-msw.c:
* menubar-msw.c (mswindows_popup_menu):
* menubar-x.c (make_dummy_xbutton_event):
* menubar-x.c (command_builder_operate_menu_accelerator):
* menubar-x.c (menu_accelerator_safe_compare):
* menubar-x.c (menu_accelerator_safe_mod_compare):
* mule-charset.c:
* mule-charset.c (make_charset):
* mule-charset.c (Fcharset_property):
* mule-coding.c:
* mule-coding.c (ccs_description_1):
* mule-coding.c (ccs_description =):
* mule-coding.c (ccsd_description_1):
* mule-coding.c (ccsd_description =):
* nt.c (getpwnam):
* nt.c (init_mswindows_environment):
* nt.c (get_cached_volume_information):
* nt.c (mswindows_is_executable):
* nt.c (read_unc_volume):
* nt.c (mswindows_access):
* nt.c (mswindows_link):
* nt.c (mswindows_fstat):
* nt.c (mswindows_stat):
* nt.c (mswindows_executable_type):
* nt.c (Fmswindows_short_file_name):
* nt.c (Fmswindows_long_file_name):
* objects-impl.h (struct Lisp_Color_Instance):
* objects-impl.h (struct Lisp_Font_Instance):
* objects-tty.c:
* objects-x.c (allocate_nearest_color):
* objects.c:
* objects.c (Fmake_color_instance):
* objects.c (Fmake_font_instance):
* objects.c (font_instantiate):
* opaque.c:
* opaque.c (make_opaque):
* opaque.c (make_opaque_ptr):
* opaque.c (reinit_opaque_early):
* opaque.c (init_opaque_once_early):
* print.c:
* print.c (printing_badness):
* print.c (printing_major_badness):
* print.c (print_internal):
* print.c (debug_p4):
* print.c (dp):
* print.c (debug_backtrace):
* process-nt.c (nt_create_process):
* process-nt.c (get_internet_address):
* process-unix.c:
* process-unix.c (struct unix_process_data):
* process-unix.c (get_internet_address):
* process-unix.c (unix_alloc_process_data):
* process-unix.c (unix_create_process):
* process-unix.c (try_to_initialize_subtty):
* process-unix.c (unix_kill_child_process):
* process-unix.c (process_type_create_unix):
* process.c:
* process.c (mark_process):
* process.c (MARKED_SLOT):
* process.c (make_process_internal):
* process.c (Fprocess_tty_name):
* process.c (decode_signal):
* process.h:
* procimpl.h:
* procimpl.h (struct process_methods):
* procimpl.h (struct Lisp_Process):
* rangetab.c:
* realpath.c (readlink_and_correct_case):
* redisplay-x.c (x_window_output_end):
* redisplay-x.c (x_redraw_exposed_area):
* redisplay-x.c (x_clear_frame):
* redisplay.c:
* redisplay.h:
* redisplay.h (struct rune_dglyph):
* redisplay.h (struct rune):
* scrollbar.c:
* scrollbar.c (create_scrollbar_instance):
* specifier.c:
* specifier.c (specifier_empty_extra_description_1):
* specifier.c (make_specifier_internal):
* specifier.c (decode_locale_type):
* specifier.c (decode_how_to_add_specification):
* specifier.h:
* specifier.h (struct specifier_methods):
* specifier.h (DEFINE_SPECIFIER_TYPE_WITH_DATA):
* specifier.h (INITIALIZE_SPECIFIER_TYPE_WITH_DATA):
* symbols.c:
* symbols.c (Fsetplist):
* symbols.c (default_value):
* symbols.c (decode_magic_handler_type):
* symbols.c (handler_type_from_function_symbol):
* symbols.c (Fdefvaralias):
* symbols.c (init_symbols_once_early):
* symbols.c (reinit_symbols_early):
* symsinit.h:
* sysdep.c (sys_subshell):
* sysdep.c (tty_init_sys_modes_on_device):
* syswindows.h:
* text.c (dfc_convert_to_external_format):
* text.c (dfc_convert_to_internal_format):
* text.c (reinit_eistring_early):
* text.c (init_eistring_once_early):
* text.c (reinit_vars_of_text):
* text.h:
* text.h (INC_IBYTEPTR_FMT):
* text.h (DEC_IBYTEPTR_FMT):
* toolbar.c:
* toolbar.c (decode_toolbar_position):
* tooltalk.c:
* ui-gtk.c:
* unexnt.c:
* unexnt.c (_start):
* unexnt.c (unexec):
* unexnt.c (get_section_info):
* unicode.c:
* unicode.c (vars_of_unicode):
* window.c:
* window.c (allocate_window):
* window.c (new_window_mirror):
* window.c (update_mirror_internal):
* winslots.h:
author | michaels |
---|---|
date | Sun, 12 Jan 2003 11:08:22 +0000 |
parents | 804517e16990 |
children | b531bf8658e9 |
rev | line source |
---|---|
428 | 1 /* Output like sprintf to a buffer of specified size. |
2 Also takes args differently: pass one pointer to an array of strings | |
3 in addition to the format string which is separate. | |
4 Copyright (C) 1995 Free Software Foundation, Inc. | |
793 | 5 Copyright (C) 2001, 2002 Ben Wing. |
428 | 6 Rewritten by mly to use varargs.h. |
7 Rewritten from scratch by Ben Wing (February 1995) for Mule; expanded | |
8 to full printf spec. | |
9 | |
10 This file is part of XEmacs. | |
11 | |
12 XEmacs is free software; you can redistribute it and/or modify it | |
13 under the terms of the GNU General Public License as published by the | |
14 Free Software Foundation; either version 2, or (at your option) any | |
15 later version. | |
16 | |
17 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
19 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 for more details. | |
21 | |
22 You should have received a copy of the GNU General Public License | |
23 along with XEmacs; see the file COPYING. If not, write to | |
24 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
25 Boston, MA 02111-1307, USA. */ | |
26 | |
793 | 27 /* Synched up with: Rewritten by Ben Wing. Not in FSF. */ |
428 | 28 |
29 #include <config.h> | |
30 #include "lisp.h" | |
31 | |
32 #include "buffer.h" | |
33 #include "lstream.h" | |
34 | |
446 | 35 static const char * const valid_flags = "-+ #0"; |
36 static const char * const valid_converters = "dic" "ouxX" "feEgG" "sS"; | |
37 static const char * const int_converters = "dic"; | |
38 static const char * const unsigned_int_converters = "ouxX"; | |
39 static const char * const double_converters = "feEgG"; | |
40 static const char * const string_converters = "sS"; | |
428 | 41 |
42 typedef struct printf_spec printf_spec; | |
43 struct printf_spec | |
44 { | |
45 int argnum; /* which argument does this spec want? This is one-based: | |
46 The first argument given is numbered 1, the second | |
47 is 2, etc. This is to handle %##$x-type specs. */ | |
48 int minwidth; | |
49 int precision; | |
50 unsigned int minus_flag:1; | |
51 unsigned int plus_flag:1; | |
52 unsigned int space_flag:1; | |
53 unsigned int number_flag:1; | |
54 unsigned int zero_flag:1; | |
55 unsigned int h_flag:1; | |
56 unsigned int l_flag:1; | |
57 unsigned int forwarding_precision:1; | |
58 char converter; /* converter character or 0 for dummy marker | |
59 indicating literal text at the end of the | |
60 specification */ | |
61 Bytecount text_before; /* position of the first character of the | |
62 block of literal text before this spec */ | |
63 Bytecount text_before_len; /* length of that text */ | |
64 }; | |
65 | |
66 typedef union printf_arg printf_arg; | |
67 union printf_arg | |
68 { | |
69 long l; | |
70 unsigned long ul; | |
71 double d; | |
867 | 72 Ibyte *bp; |
428 | 73 }; |
74 | |
75 /* We maintain a list of all the % specs in the specification, | |
76 along with the offset and length of the block of literal text | |
77 before each spec. In addition, we have a "dummy" spec that | |
78 represents all the literal text at the end of the specification. | |
79 Its converter is 0. */ | |
80 | |
81 typedef struct | |
82 { | |
83 Dynarr_declare (struct printf_spec); | |
84 } printf_spec_dynarr; | |
85 | |
86 typedef struct | |
87 { | |
88 Dynarr_declare (union printf_arg); | |
89 } printf_arg_dynarr; | |
90 | |
448 | 91 /* Append STRING (of length LEN bytes) to STREAM. |
92 MINLEN is the minimum field width. | |
93 If MINUS_FLAG is set, left-justify the string in its field; | |
94 otherwise, right-justify. | |
95 If ZERO_FLAG is set, pad with 0's; otherwise pad with spaces. | |
96 If MAXLEN is non-negative, the string is first truncated on the | |
97 right to that many characters. | |
428 | 98 |
99 Note that MINLEN and MAXLEN are Charcounts but LEN is a Bytecount. */ | |
100 | |
101 static void | |
867 | 102 doprnt_2 (Lisp_Object stream, const Ibyte *string, Bytecount len, |
428 | 103 Charcount minlen, Charcount maxlen, int minus_flag, int zero_flag) |
104 { | |
105 Lstream *lstr = XLSTREAM (stream); | |
448 | 106 Charcount cclen = bytecount_to_charcount (string, len); |
107 int to_add = minlen - cclen; | |
428 | 108 |
109 /* Padding at beginning to right-justify ... */ | |
448 | 110 if (!minus_flag) |
111 while (to_add-- > 0) | |
112 Lstream_putc (lstr, zero_flag ? '0' : ' '); | |
428 | 113 |
448 | 114 if (0 <= maxlen && maxlen < cclen) |
115 len = charcount_to_bytecount (string, maxlen); | |
428 | 116 Lstream_write (lstr, string, len); |
117 | |
118 /* Padding at end to left-justify ... */ | |
448 | 119 if (minus_flag) |
120 while (to_add-- > 0) | |
121 Lstream_putc (lstr, zero_flag ? '0' : ' '); | |
428 | 122 } |
123 | |
867 | 124 static const Ibyte * |
125 parse_off_posnum (const Ibyte *start, const Ibyte *end, int *returned_num) | |
428 | 126 { |
867 | 127 Ibyte arg_convert[100]; |
128 REGISTER Ibyte *arg_ptr = arg_convert; | |
428 | 129 |
130 *returned_num = -1; | |
131 while (start != end && isdigit (*start)) | |
132 { | |
647 | 133 if (arg_ptr - arg_convert >= (int) sizeof (arg_convert) - 1) |
134 syntax_error ("Format converter number too large", Qunbound); | |
428 | 135 *arg_ptr++ = *start++; |
136 } | |
137 *arg_ptr = '\0'; | |
138 if (arg_convert != arg_ptr) | |
139 *returned_num = atoi ((char *) arg_convert); | |
140 return start; | |
141 } | |
142 | |
793 | 143 #define NEXT_ASCII_BYTE(ch) \ |
144 do { \ | |
145 if (fmt == fmt_end) \ | |
146 syntax_error ("Premature end of format string", Qunbound); \ | |
147 ch = *fmt; \ | |
148 if (ch >= 0200) \ | |
149 syntax_error ("Non-ASCII character in format converter spec", \ | |
150 Qunbound); \ | |
151 fmt++; \ | |
428 | 152 } while (0) |
153 | |
154 #define RESOLVE_FLAG_CONFLICTS(spec) \ | |
155 do { \ | |
156 if (spec.space_flag && spec.plus_flag) \ | |
157 spec.space_flag = 0; \ | |
158 if (spec.zero_flag && spec.space_flag) \ | |
159 spec.zero_flag = 0; \ | |
160 } while (0) | |
161 | |
162 static printf_spec_dynarr * | |
867 | 163 parse_doprnt_spec (const Ibyte *format, Bytecount format_length) |
428 | 164 { |
867 | 165 const Ibyte *fmt = format; |
166 const Ibyte *fmt_end = format + format_length; | |
428 | 167 printf_spec_dynarr *specs = Dynarr_new (printf_spec); |
168 int prev_argnum = 0; | |
169 | |
170 while (1) | |
171 { | |
172 struct printf_spec spec; | |
867 | 173 const Ibyte *text_end; |
174 Ibyte ch; | |
428 | 175 |
176 xzero (spec); | |
177 if (fmt == fmt_end) | |
178 return specs; | |
867 | 179 text_end = (Ibyte *) memchr (fmt, '%', fmt_end - fmt); |
428 | 180 if (!text_end) |
181 text_end = fmt_end; | |
182 spec.text_before = fmt - format; | |
183 spec.text_before_len = text_end - fmt; | |
184 fmt = text_end; | |
185 if (fmt != fmt_end) | |
186 { | |
187 fmt++; /* skip over % */ | |
188 | |
189 /* A % is special -- no arg number. According to ANSI specs, | |
190 field width does not apply to %% conversion. */ | |
191 if (fmt != fmt_end && *fmt == '%') | |
192 { | |
193 spec.converter = '%'; | |
194 Dynarr_add (specs, spec); | |
195 fmt++; | |
196 continue; | |
197 } | |
198 | |
199 /* Is there a field number specifier? */ | |
200 { | |
867 | 201 const Ibyte *ptr; |
428 | 202 int fieldspec; |
203 | |
204 ptr = parse_off_posnum (fmt, fmt_end, &fieldspec); | |
205 if (fieldspec > 0 && ptr != fmt_end && *ptr == '$') | |
206 { | |
207 /* There is a format specifier */ | |
208 prev_argnum = fieldspec; | |
209 fmt = ptr + 1; | |
210 } | |
211 else | |
212 prev_argnum++; | |
213 spec.argnum = prev_argnum; | |
214 } | |
215 | |
216 /* Parse off any flags */ | |
217 NEXT_ASCII_BYTE (ch); | |
218 while (strchr (valid_flags, ch)) | |
219 { | |
220 switch (ch) | |
221 { | |
446 | 222 case '-': spec.minus_flag = 1; break; |
223 case '+': spec.plus_flag = 1; break; | |
224 case ' ': spec.space_flag = 1; break; | |
428 | 225 case '#': spec.number_flag = 1; break; |
446 | 226 case '0': spec.zero_flag = 1; break; |
428 | 227 default: abort (); |
228 } | |
229 NEXT_ASCII_BYTE (ch); | |
230 } | |
231 | |
232 /* Parse off the minimum field width */ | |
233 fmt--; /* back up */ | |
234 | |
235 /* | |
236 * * means the field width was passed as an argument. | |
237 * Mark the current spec as one that forwards its | |
238 * field width and flags to the next spec in the array. | |
239 * Then create a new spec and continue with the parsing. | |
240 */ | |
241 if (fmt != fmt_end && *fmt == '*') | |
242 { | |
243 spec.converter = '*'; | |
244 RESOLVE_FLAG_CONFLICTS(spec); | |
245 Dynarr_add (specs, spec); | |
246 xzero (spec); | |
247 spec.argnum = ++prev_argnum; | |
248 fmt++; | |
249 } | |
250 else | |
251 { | |
252 fmt = parse_off_posnum (fmt, fmt_end, &spec.minwidth); | |
253 if (spec.minwidth == -1) | |
254 spec.minwidth = 0; | |
255 } | |
256 | |
257 /* Parse off any precision specified */ | |
258 NEXT_ASCII_BYTE (ch); | |
259 if (ch == '.') | |
260 { | |
261 /* | |
262 * * means the precision was passed as an argument. | |
263 * Mark the current spec as one that forwards its | |
264 * fieldwidth, flags and precision to the next spec in | |
265 * the array. Then create a new spec and continue | |
266 * with the parse. | |
267 */ | |
268 if (fmt != fmt_end && *fmt == '*') | |
269 { | |
270 spec.converter = '*'; | |
271 spec.forwarding_precision = 1; | |
272 RESOLVE_FLAG_CONFLICTS(spec); | |
273 Dynarr_add (specs, spec); | |
274 xzero (spec); | |
275 spec.argnum = ++prev_argnum; | |
276 fmt++; | |
277 } | |
278 else | |
279 { | |
280 fmt = parse_off_posnum (fmt, fmt_end, &spec.precision); | |
281 if (spec.precision == -1) | |
282 spec.precision = 0; | |
283 } | |
284 NEXT_ASCII_BYTE (ch); | |
285 } | |
286 else | |
287 /* No precision specified */ | |
288 spec.precision = -1; | |
289 | |
290 /* Parse off h or l flag */ | |
291 if (ch == 'h' || ch == 'l') | |
292 { | |
293 if (ch == 'h') | |
294 spec.h_flag = 1; | |
295 else | |
296 spec.l_flag = 1; | |
297 NEXT_ASCII_BYTE (ch); | |
298 } | |
299 | |
300 if (!strchr (valid_converters, ch)) | |
563 | 301 syntax_error ("Invalid converter character", make_char (ch)); |
428 | 302 spec.converter = ch; |
303 } | |
304 | |
305 RESOLVE_FLAG_CONFLICTS(spec); | |
306 Dynarr_add (specs, spec); | |
307 } | |
308 | |
1204 | 309 RETURN_NOT_REACHED(specs); /* suppress compiler warning */ |
428 | 310 } |
311 | |
312 static int | |
313 get_args_needed (printf_spec_dynarr *specs) | |
314 { | |
315 int args_needed = 0; | |
316 REGISTER int i; | |
317 | |
318 /* Figure out how many args are needed. This may be less than | |
319 the number of specs because a spec could be %% or could be | |
320 missing (literal text at end of format string) or there | |
321 could be specs where the field number is explicitly given. | |
322 We just look for the maximum argument number that's referenced. */ | |
323 | |
324 for (i = 0; i < Dynarr_length (specs); i++) | |
325 { | |
326 char ch = Dynarr_at (specs, i).converter; | |
327 if (ch && ch != '%') | |
328 { | |
329 int argnum = Dynarr_at (specs, i).argnum; | |
330 if (argnum > args_needed) | |
331 args_needed = argnum; | |
332 } | |
333 } | |
334 | |
335 return args_needed; | |
336 } | |
337 | |
338 static printf_arg_dynarr * | |
339 get_doprnt_args (printf_spec_dynarr *specs, va_list vargs) | |
340 { | |
341 printf_arg_dynarr *args = Dynarr_new (printf_arg); | |
342 union printf_arg arg; | |
343 REGISTER int i; | |
344 int args_needed = get_args_needed (specs); | |
345 | |
346 xzero (arg); | |
347 for (i = 1; i <= args_needed; i++) | |
348 { | |
349 int j; | |
350 char ch; | |
351 struct printf_spec *spec = 0; | |
352 | |
353 for (j = 0; j < Dynarr_length (specs); j++) | |
354 { | |
355 spec = Dynarr_atp (specs, j); | |
356 if (spec->argnum == i) | |
357 break; | |
358 } | |
359 | |
360 if (j == Dynarr_length (specs)) | |
563 | 361 syntax_error ("No conversion spec for argument", make_int (i)); |
428 | 362 |
363 ch = spec->converter; | |
364 | |
365 if (strchr (int_converters, ch)) | |
366 { | |
446 | 367 if (spec->l_flag) |
428 | 368 arg.l = va_arg (vargs, long); |
369 else | |
446 | 370 /* int even if ch == 'c' or spec->h_flag: |
371 "the type used in va_arg is supposed to match the | |
372 actual type **after default promotions**." | |
373 Hence we read an int, not a short, if spec->h_flag. */ | |
374 arg.l = va_arg (vargs, int); | |
428 | 375 } |
376 else if (strchr (unsigned_int_converters, ch)) | |
377 { | |
446 | 378 if (spec->l_flag) |
428 | 379 arg.ul = va_arg (vargs, unsigned long); |
380 else | |
446 | 381 /* unsigned int even if ch == 'c' or spec->h_flag */ |
382 arg.ul = (unsigned long) va_arg (vargs, unsigned int); | |
428 | 383 } |
384 else if (strchr (double_converters, ch)) | |
385 arg.d = va_arg (vargs, double); | |
386 else if (strchr (string_converters, ch)) | |
867 | 387 arg.bp = va_arg (vargs, Ibyte *); |
428 | 388 else abort (); |
389 | |
390 Dynarr_add (args, arg); | |
391 } | |
392 | |
393 return args; | |
394 } | |
395 | |
771 | 396 /* Most basic entry point into string formatting. |
397 | |
398 Generate output from a format-spec (either a Lisp string | |
399 FORMAT_RELOC, or a C string FORMAT_NONRELOC of length FORMAT_LENGTH | |
400 -- which *MUST NOT* come from Lisp string data, unless GC is | |
401 inhibited). Output goes to STREAM. Returns the number of bytes | |
402 stored into STREAM. Arguments are either C-type arguments in | |
403 va_list VARGS, or an array of Lisp objects in LARGS of size | |
404 NARGS. (Behavior is different in the two cases -- you either get | |
405 standard sprintf() behavior or `format' behavior.) */ | |
428 | 406 |
407 static Bytecount | |
867 | 408 emacs_doprnt_1 (Lisp_Object stream, const Ibyte *format_nonreloc, |
771 | 409 Bytecount format_length, Lisp_Object format_reloc, |
410 int nargs, const Lisp_Object *largs, va_list vargs) | |
428 | 411 { |
412 printf_spec_dynarr *specs = 0; | |
413 printf_arg_dynarr *args = 0; | |
414 REGISTER int i; | |
415 int init_byte_count = Lstream_byte_count (XLSTREAM (stream)); | |
771 | 416 int count; |
428 | 417 |
418 if (!NILP (format_reloc)) | |
419 { | |
420 format_nonreloc = XSTRING_DATA (format_reloc); | |
421 format_length = XSTRING_LENGTH (format_reloc); | |
422 } | |
423 if (format_length < 0) | |
442 | 424 format_length = (Bytecount) strlen ((const char *) format_nonreloc); |
428 | 425 |
426 specs = parse_doprnt_spec (format_nonreloc, format_length); | |
771 | 427 count = record_unwind_protect_freeing_dynarr (specs); |
428 | |
428 | 429 if (largs) |
430 { | |
446 | 431 /* allow too many args for string, but not too few */ |
428 | 432 if (nargs < get_args_needed (specs)) |
563 | 433 signal_error_1 (Qwrong_number_of_arguments, |
428 | 434 list3 (Qformat, |
435 make_int (nargs), | |
436 !NILP (format_reloc) ? format_reloc : | |
437 make_string (format_nonreloc, format_length))); | |
438 } | |
439 else | |
440 { | |
441 args = get_doprnt_args (specs, vargs); | |
771 | 442 record_unwind_protect_freeing_dynarr (args); |
428 | 443 } |
444 | |
445 for (i = 0; i < Dynarr_length (specs); i++) | |
446 { | |
447 struct printf_spec *spec = Dynarr_atp (specs, i); | |
448 char ch; | |
449 | |
450 /* Copy the text before */ | |
451 if (!NILP (format_reloc)) /* refetch in case of GC below */ | |
452 format_nonreloc = XSTRING_DATA (format_reloc); | |
446 | 453 |
771 | 454 doprnt_2 (stream, format_nonreloc + spec->text_before, |
446 | 455 spec->text_before_len, 0, -1, 0, 0); |
428 | 456 |
457 ch = spec->converter; | |
458 | |
459 if (!ch) | |
460 continue; | |
461 | |
462 if (ch == '%') | |
463 { | |
867 | 464 doprnt_2 (stream, (Ibyte *) &ch, 1, 0, -1, 0, 0); |
428 | 465 continue; |
466 } | |
467 | |
468 /* The char '*' as converter means the field width, precision | |
469 was specified as an argument. Extract the data and forward | |
470 it to the next spec, to which it will apply. */ | |
471 if (ch == '*') | |
472 { | |
473 struct printf_spec *nextspec = Dynarr_atp (specs, i + 1); | |
474 Lisp_Object obj = largs[spec->argnum - 1]; | |
475 | |
476 if (INTP (obj)) | |
477 { | |
478 if (spec->forwarding_precision) | |
479 { | |
480 nextspec->precision = XINT (obj); | |
481 nextspec->minwidth = spec->minwidth; | |
482 } | |
483 else | |
484 { | |
485 nextspec->minwidth = XINT (obj); | |
446 | 486 if (XINT (obj) < 0) |
428 | 487 { |
488 spec->minus_flag = 1; | |
489 nextspec->minwidth = - nextspec->minwidth; | |
490 } | |
491 } | |
446 | 492 nextspec->minus_flag = spec->minus_flag; |
493 nextspec->plus_flag = spec->plus_flag; | |
494 nextspec->space_flag = spec->space_flag; | |
428 | 495 nextspec->number_flag = spec->number_flag; |
446 | 496 nextspec->zero_flag = spec->zero_flag; |
428 | 497 } |
498 continue; | |
499 } | |
500 | |
501 if (largs && (spec->argnum < 1 || spec->argnum > nargs)) | |
771 | 502 syntax_error ("Invalid repositioning argument", |
503 make_int (spec->argnum)); | |
428 | 504 |
505 else if (ch == 'S' || ch == 's') | |
506 { | |
867 | 507 Ibyte *string; |
428 | 508 Bytecount string_len; |
509 | |
510 if (!largs) | |
511 { | |
512 string = Dynarr_at (args, spec->argnum - 1).bp; | |
771 | 513 #if 0 |
514 /* [[ error() can be called with null string arguments. | |
428 | 515 E.g., in fileio.c, the return value of strerror() |
516 is never checked. We'll print (null), like some | |
517 printf implementations do. Would it be better (and safe) | |
518 to signal an error instead? Or should we just use the | |
771 | 519 empty string? -dkindred@cs.cmu.edu 8/1997 ]] |
520 Do not hide bugs. --ben | |
428 | 521 */ |
522 if (!string) | |
867 | 523 string = (Ibyte *) "(null)"; |
771 | 524 #else |
525 assert (string); | |
526 #endif | |
428 | 527 string_len = strlen ((char *) string); |
528 } | |
529 else | |
530 { | |
531 Lisp_Object obj = largs[spec->argnum - 1]; | |
793 | 532 Lisp_Object ls; |
428 | 533 |
534 if (ch == 'S') | |
535 { | |
536 /* For `S', prin1 the argument and then treat like | |
537 a string. */ | |
793 | 538 ls = Fprin1_to_string (obj, Qnil); |
428 | 539 } |
540 else if (STRINGP (obj)) | |
793 | 541 ls = obj; |
428 | 542 else if (SYMBOLP (obj)) |
543 ls = XSYMBOL (obj)->name; | |
544 else | |
545 { | |
546 /* convert to string using princ. */ | |
793 | 547 ls = Fprin1_to_string (obj, Qt); |
428 | 548 } |
793 | 549 string = XSTRING_DATA (ls); |
550 string_len = XSTRING_LENGTH (ls); | |
428 | 551 } |
552 | |
771 | 553 doprnt_2 (stream, string, string_len, spec->minwidth, |
428 | 554 spec->precision, spec->minus_flag, spec->zero_flag); |
555 } | |
556 | |
557 else | |
558 { | |
559 /* Must be a number. */ | |
560 union printf_arg arg; | |
561 | |
562 if (!largs) | |
563 { | |
564 arg = Dynarr_at (args, spec->argnum - 1); | |
565 } | |
566 else | |
567 { | |
568 Lisp_Object obj = largs[spec->argnum - 1]; | |
569 if (CHARP (obj)) | |
570 obj = make_int (XCHAR (obj)); | |
571 if (!INT_OR_FLOATP (obj)) | |
572 { | |
793 | 573 syntax_error |
574 ("format specifier %%%c doesn't match argument type", | |
575 make_char (ch)); | |
428 | 576 } |
577 else if (strchr (double_converters, ch)) | |
578 arg.d = XFLOATINT (obj); | |
579 else | |
580 { | |
446 | 581 if (FLOATP (obj)) |
582 obj = Ftruncate (obj); | |
428 | 583 |
584 if (strchr (unsigned_int_converters, ch)) | |
446 | 585 arg.ul = (unsigned long) XINT (obj); |
428 | 586 else |
446 | 587 arg.l = XINT (obj); |
428 | 588 } |
589 } | |
590 | |
591 | |
592 if (ch == 'c') | |
593 { | |
867 | 594 Ichar a; |
428 | 595 Bytecount charlen; |
867 | 596 Ibyte charbuf[MAX_ICHAR_LEN]; |
428 | 597 |
867 | 598 a = (Ichar) arg.l; |
428 | 599 |
867 | 600 if (!valid_ichar_p (a)) |
793 | 601 syntax_error ("invalid character value %d to %%c spec", |
831 | 602 make_int (a)); |
428 | 603 |
867 | 604 charlen = set_itext_ichar (charbuf, a); |
771 | 605 doprnt_2 (stream, charbuf, charlen, spec->minwidth, |
428 | 606 -1, spec->minus_flag, spec->zero_flag); |
607 } | |
608 else | |
609 { | |
448 | 610 /* ASCII Decimal representation uses 2.4 times as many |
611 bits as machine binary. */ | |
612 char *text_to_print = | |
613 alloca_array (char, 32 + | |
614 max (spec->minwidth, | |
647 | 615 (int) max (sizeof (double), |
616 sizeof (long)) * 3 + | |
448 | 617 max (spec->precision, 0))); |
428 | 618 char constructed_spec[100]; |
446 | 619 char *p = constructed_spec; |
428 | 620 |
448 | 621 /* Mostly reconstruct the spec and use sprintf() to |
428 | 622 format the string. */ |
623 | |
446 | 624 *p++ = '%'; |
625 if (spec->plus_flag) *p++ = '+'; | |
626 if (spec->space_flag) *p++ = ' '; | |
627 if (spec->number_flag) *p++ = '#'; | |
448 | 628 if (spec->minus_flag) *p++ = '-'; |
629 if (spec->zero_flag) *p++ = '0'; | |
446 | 630 |
448 | 631 if (spec->minwidth >= 0) |
577 | 632 { |
633 long_to_string (p, spec->minwidth); | |
634 p += strlen (p); | |
635 } | |
448 | 636 if (spec->precision >= 0) |
428 | 637 { |
446 | 638 *p++ = '.'; |
577 | 639 long_to_string (p, spec->precision); |
640 p += strlen (p); | |
428 | 641 } |
448 | 642 |
428 | 643 if (strchr (double_converters, ch)) |
442 | 644 { |
446 | 645 *p++ = ch; |
646 *p++ = '\0'; | |
442 | 647 sprintf (text_to_print, constructed_spec, arg.d); |
648 } | |
428 | 649 else |
650 { | |
448 | 651 *p++ = 'l'; /* Always use longs with sprintf() */ |
652 *p++ = ch; | |
653 *p++ = '\0'; | |
446 | 654 |
655 if (strchr (unsigned_int_converters, ch)) | |
656 sprintf (text_to_print, constructed_spec, arg.ul); | |
657 else | |
428 | 658 sprintf (text_to_print, constructed_spec, arg.l); |
659 } | |
660 | |
867 | 661 doprnt_2 (stream, (Ibyte *) text_to_print, |
448 | 662 strlen (text_to_print), 0, -1, 0, 0); |
428 | 663 } |
664 } | |
665 } | |
666 | |
771 | 667 unbind_to (count); |
428 | 668 return Lstream_byte_count (XLSTREAM (stream)) - init_byte_count; |
669 } | |
670 | |
771 | 671 /* Basic external entry point into string formatting. See |
672 emacs_doprnt_1(). | |
673 */ | |
674 | |
675 Bytecount | |
867 | 676 emacs_doprnt_va (Lisp_Object stream, const Ibyte *format_nonreloc, |
771 | 677 Bytecount format_length, Lisp_Object format_reloc, |
678 va_list vargs) | |
679 { | |
680 return emacs_doprnt_1 (stream, format_nonreloc, format_length, | |
681 format_reloc, 0, 0, vargs); | |
682 } | |
683 | |
684 /* Basic external entry point into string formatting. See | |
685 emacs_doprnt_1(). | |
686 */ | |
687 | |
688 Bytecount | |
867 | 689 emacs_doprnt (Lisp_Object stream, const Ibyte *format_nonreloc, |
771 | 690 Bytecount format_length, Lisp_Object format_reloc, |
691 int nargs, const Lisp_Object *largs, ...) | |
428 | 692 { |
693 va_list vargs; | |
694 Bytecount val; | |
695 va_start (vargs, largs); | |
771 | 696 val = emacs_doprnt_1 (stream, format_nonreloc, format_length, |
697 format_reloc, nargs, largs, vargs); | |
428 | 698 va_end (vargs); |
699 return val; | |
700 } | |
701 | |
771 | 702 /* Similar to `format' in that its arguments are Lisp objects rather than C |
703 objects. (For the versions that take C objects, see the | |
704 emacs_[v]sprintf... functions below.) Accepts the format string as | |
705 either a C string (FORMAT_NONRELOC, which *MUST NOT* come from Lisp | |
706 string data, unless GC is inhibited) or a Lisp string (FORMAT_RELOC). | |
707 Return resulting formatted string as a Lisp string. | |
428 | 708 |
771 | 709 All arguments are GCPRO'd, including FORMAT_RELOC; this makes it OK to |
710 pass newly created objects into this function (as often happens). | |
428 | 711 |
771 | 712 #### It shouldn't be necessary to specify the number of arguments. |
713 This would require some rewriting of the doprnt() functions, though. | |
714 */ | |
428 | 715 |
716 Lisp_Object | |
867 | 717 emacs_vsprintf_string_lisp (const CIbyte *format_nonreloc, |
771 | 718 Lisp_Object format_reloc, int nargs, |
719 const Lisp_Object *largs) | |
428 | 720 { |
771 | 721 Lisp_Object stream; |
428 | 722 Lisp_Object obj; |
771 | 723 struct gcpro gcpro1, gcpro2; |
724 GCPRO2 (largs[0], format_reloc); | |
725 gcpro1.nvars = nargs; | |
428 | 726 |
771 | 727 stream = make_resizing_buffer_output_stream (); |
867 | 728 emacs_doprnt (stream, (Ibyte *) format_nonreloc, format_nonreloc ? |
771 | 729 strlen (format_nonreloc) : 0, |
730 format_reloc, nargs, largs); | |
428 | 731 Lstream_flush (XLSTREAM (stream)); |
732 obj = make_string (resizing_buffer_stream_ptr (XLSTREAM (stream)), | |
733 Lstream_byte_count (XLSTREAM (stream))); | |
771 | 734 Lstream_delete (XLSTREAM (stream)); |
428 | 735 UNGCPRO; |
736 return obj; | |
737 } | |
738 | |
771 | 739 /* Like emacs_vsprintf_string_lisp() but accepts its extra args directly |
740 (using variable arguments), rather than as an array. */ | |
741 | |
428 | 742 Lisp_Object |
867 | 743 emacs_sprintf_string_lisp (const CIbyte *format_nonreloc, |
771 | 744 Lisp_Object format_reloc, int nargs, ...) |
428 | 745 { |
771 | 746 Lisp_Object *args = alloca_array (Lisp_Object, nargs); |
747 va_list va; | |
748 int i; | |
428 | 749 Lisp_Object obj; |
750 | |
771 | 751 va_start (va, nargs); |
752 for (i = 0; i < nargs; i++) | |
753 args[i] = va_arg (va, Lisp_Object); | |
754 va_end (va); | |
755 obj = emacs_vsprintf_string_lisp (format_nonreloc, format_reloc, nargs, | |
756 args); | |
428 | 757 return obj; |
758 } | |
759 | |
771 | 760 /* Like emacs_vsprintf_string_lisp() but returns a malloc()ed memory block. |
761 Return length out through LEN_OUT, if not null. */ | |
762 | |
867 | 763 Ibyte * |
764 emacs_vsprintf_malloc_lisp (const CIbyte *format_nonreloc, | |
771 | 765 Lisp_Object format_reloc, int nargs, |
766 const Lisp_Object *largs, Bytecount *len_out) | |
767 { | |
768 Lisp_Object stream; | |
867 | 769 Ibyte *retval; |
771 | 770 Bytecount len; |
771 struct gcpro gcpro1, gcpro2; | |
772 | |
773 GCPRO2 (largs[0], format_reloc); | |
774 gcpro1.nvars = nargs; | |
775 | |
776 stream = make_resizing_buffer_output_stream (); | |
867 | 777 emacs_doprnt (stream, (Ibyte *) format_nonreloc, format_nonreloc ? |
771 | 778 strlen (format_nonreloc) : 0, |
779 format_reloc, nargs, largs); | |
780 Lstream_flush (XLSTREAM (stream)); | |
781 len = Lstream_byte_count (XLSTREAM (stream)); | |
867 | 782 retval = (Ibyte *) xmalloc (len + 1); |
771 | 783 memcpy (retval, resizing_buffer_stream_ptr (XLSTREAM (stream)), len); |
784 retval[len] = '\0'; | |
785 Lstream_delete (XLSTREAM (stream)); | |
786 | |
787 if (len_out) | |
788 *len_out = len; | |
789 UNGCPRO; | |
790 return retval; | |
791 } | |
792 | |
793 /* Like emacs_sprintf_string_lisp() but returns a malloc()ed memory block. | |
794 Return length out through LEN_OUT, if not null. */ | |
795 | |
867 | 796 Ibyte * |
797 emacs_sprintf_malloc_lisp (Bytecount *len_out, const CIbyte *format_nonreloc, | |
771 | 798 Lisp_Object format_reloc, int nargs, ...) |
799 { | |
800 Lisp_Object *args = alloca_array (Lisp_Object, nargs); | |
801 va_list va; | |
802 int i; | |
867 | 803 Ibyte *retval; |
771 | 804 |
805 va_start (va, nargs); | |
806 for (i = 0; i < nargs; i++) | |
807 args[i] = va_arg (va, Lisp_Object); | |
808 va_end (va); | |
809 retval = emacs_vsprintf_malloc_lisp (format_nonreloc, format_reloc, nargs, | |
810 args, len_out); | |
811 return retval; | |
812 } | |
813 | |
814 /* vsprintf()-like replacement. Returns a Lisp string. Data | |
815 from Lisp strings is OK because we explicitly inhibit GC. */ | |
816 | |
428 | 817 Lisp_Object |
867 | 818 emacs_vsprintf_string (const CIbyte *format, va_list vargs) |
428 | 819 { |
771 | 820 Lisp_Object stream = make_resizing_buffer_output_stream (); |
428 | 821 Lisp_Object obj; |
771 | 822 int count = begin_gc_forbidden (); |
428 | 823 |
867 | 824 emacs_doprnt_va (stream, (Ibyte *) format, strlen (format), Qnil, |
771 | 825 vargs); |
428 | 826 Lstream_flush (XLSTREAM (stream)); |
827 obj = make_string (resizing_buffer_stream_ptr (XLSTREAM (stream)), | |
828 Lstream_byte_count (XLSTREAM (stream))); | |
829 Lstream_delete (XLSTREAM (stream)); | |
771 | 830 end_gc_forbidden (count); |
428 | 831 return obj; |
832 } | |
833 | |
771 | 834 /* sprintf()-like replacement. Returns a Lisp string. Data |
835 from Lisp strings is OK because we explicitly inhibit GC. */ | |
836 | |
428 | 837 Lisp_Object |
867 | 838 emacs_sprintf_string (const CIbyte *format, ...) |
771 | 839 { |
840 va_list vargs; | |
841 Lisp_Object retval; | |
842 | |
843 va_start (vargs, format); | |
844 retval = emacs_vsprintf_string (format, vargs); | |
845 va_end (vargs); | |
846 return retval; | |
847 } | |
848 | |
849 /* vsprintf()-like replacement. Returns a malloc()ed memory block. Data | |
850 from Lisp strings is OK because we explicitly inhibit GC. Return | |
851 length out through LEN_OUT, if not null. */ | |
852 | |
867 | 853 Ibyte * |
854 emacs_vsprintf_malloc (const CIbyte *format, va_list vargs, | |
771 | 855 Bytecount *len_out) |
428 | 856 { |
771 | 857 int count = begin_gc_forbidden (); |
428 | 858 Lisp_Object stream = make_resizing_buffer_output_stream (); |
867 | 859 Ibyte *retval; |
771 | 860 Bytecount len; |
861 | |
867 | 862 emacs_doprnt_va (stream, (Ibyte *) format, strlen (format), Qnil, |
771 | 863 vargs); |
864 Lstream_flush (XLSTREAM (stream)); | |
865 len = Lstream_byte_count (XLSTREAM (stream)); | |
867 | 866 retval = (Ibyte *) xmalloc (len + 1); |
771 | 867 memcpy (retval, resizing_buffer_stream_ptr (XLSTREAM (stream)), len); |
868 retval[len] = '\0'; | |
869 end_gc_forbidden (count); | |
870 Lstream_delete (XLSTREAM (stream)); | |
871 | |
872 if (len_out) | |
873 *len_out = len; | |
874 return retval; | |
875 } | |
876 | |
877 /* sprintf()-like replacement. Returns a malloc()ed memory block. Data | |
878 from Lisp strings is OK because we explicitly inhibit GC. Return length | |
879 out through LEN_OUT, if not null. */ | |
428 | 880 |
867 | 881 Ibyte * |
882 emacs_sprintf_malloc (Bytecount *len_out, const CIbyte *format, ...) | |
771 | 883 { |
884 va_list vargs; | |
867 | 885 Ibyte *retval; |
771 | 886 |
887 va_start (vargs, format); | |
888 retval = emacs_vsprintf_malloc (format, vargs, len_out); | |
428 | 889 va_end (vargs); |
771 | 890 return retval; |
891 } | |
892 | |
893 /* vsprintf() replacement. Writes output into OUTPUT, which better | |
894 have enough space for the output. Data from Lisp strings is OK | |
895 because we explicitly inhibit GC. */ | |
896 | |
897 Bytecount | |
867 | 898 emacs_vsprintf (Ibyte *output, const CIbyte *format, va_list vargs) |
771 | 899 { |
900 Bytecount retval; | |
901 int count = begin_gc_forbidden (); | |
902 Lisp_Object stream = make_resizing_buffer_output_stream (); | |
903 Bytecount len; | |
428 | 904 |
867 | 905 retval = emacs_doprnt_va (stream, (Ibyte *) format, strlen (format), Qnil, |
771 | 906 vargs); |
428 | 907 Lstream_flush (XLSTREAM (stream)); |
771 | 908 len = Lstream_byte_count (XLSTREAM (stream)); |
909 memcpy (output, resizing_buffer_stream_ptr (XLSTREAM (stream)), len); | |
910 output[len] = '\0'; | |
911 end_gc_forbidden (count); | |
428 | 912 Lstream_delete (XLSTREAM (stream)); |
771 | 913 |
914 return retval; | |
428 | 915 } |
771 | 916 |
917 /* sprintf() replacement. Writes output into OUTPUT, which better | |
918 have enough space for the output. Data from Lisp strings is OK | |
919 because we explicitly inhibit GC. */ | |
920 | |
921 Bytecount | |
867 | 922 emacs_sprintf (Ibyte *output, const CIbyte *format, ...) |
771 | 923 { |
924 va_list vargs; | |
925 Bytecount retval; | |
926 | |
927 va_start (vargs, format); | |
928 retval = emacs_vsprintf (output, format, vargs); | |
929 va_end (vargs); | |
930 return retval; | |
931 } |