Angband
Functions | Variables
z-form.c File Reference

Low-level text formatting (snprintf() replacement) More...

#include "z-form.h"
#include "z-type.h"
#include "z-util.h"
#include "z-virt.h"

Functions

size_t vstrnfmt (char *buf, size_t max, const char *fmt, va_list vp)
 Here is some information about the routines in this file. More...
 
void strnfcat (char *str, size_t max, size_t *end, const char *fmt,...)
 Add a formatted string to the end of a string. More...
 
char * vformat (const char *fmt, va_list vp)
 Do a vstrnfmt (see above) into a (growable) static buffer. More...
 
void vformat_kill (void)
 Free the memory allocated for the format buffer. More...
 
size_t strnfmt (char *buf, size_t max, const char *fmt,...)
 Do a vstrnfmt (see above) into a buffer of a given size. More...
 
char * format (const char *fmt,...)
 Do a vstrnfmt() into (see above) into a (growable) static buffer. More...
 
void plog_fmt (const char *fmt,...)
 Vararg interface to plog() More...
 
void quit_fmt (const char *fmt,...)
 Vararg interface to quit() More...
 

Variables

static char * format_buf = NULL
 
static size_t format_len = 0
 

Detailed Description

Low-level text formatting (snprintf() replacement)

Copyright (c) 1997 Ben Harrison

This work is free software; you can redistribute it and/or modify it under the terms of either:

a) the GNU General Public License as published by the Free Software Foundation, version 2, or

b) the "Angband licence": This software may be copied and distributed for educational, research, and not for profit purposes provided that this copyright and statement are included in all such copies. Other copyrights may also apply.

Function Documentation

◆ format()

char* format ( const char *  fmt,
  ... 
)

Do a vstrnfmt() into (see above) into a (growable) static buffer.

Simple interface to "vformat()".

This buffer is usable for very short term formatting of results. Note that the buffer is (technically) writable, but only up to the length of the string contained inside it.

References vformat().

Referenced by activate_randart_file(), collect_slay_brand_stats(), colors_modify(), context_menu_cave(), context_menu_object(), context_menu_player_display_floor(), context_menu_store_item(), death_info(), desc_ego_fake(), describe_artifact(), describe_combat(), describe_effect(), describe_light(), dir_create(), display_group_member(), display_knowledge(), display_menu_row(), display_monster(), display_resistance_panel(), display_scores_aux(), do_cmd_delay(), do_cmd_hp_warn(), do_cmd_lazymove_delay(), do_cmd_message_one(), do_cmd_messages(), do_cmd_pref_file_hack(), do_cmd_version(), do_cmd_wield(), do_cmd_wiz_hack_nick(), ego_display(), equip_describe(), equip_mention(), file_archive(), get_file_text(), get_pref_path(), get_vault_monsters(), ignore_sval_menu_display(), init_arrays(), lore_append_abilities(), lore_append_drop(), lore_append_exp(), mon_restrict(), mon_summary(), mon_take_hit(), object_power(), option_toggle_display(), option_toggle_handle(), parse_file(), parse_file_quit_not_found(), point_based_points(), prt_depth(), prt_speed(), prt_study(), prt_welcome(), py_attack_real(), quality_display(), ranged_helper(), rd_artifacts(), rd_dungeon(), rd_history(), rd_ignore(), rd_item(), rd_monster(), rd_monster_memory(), rd_monsters_aux(), rd_object_memory(), rd_player(), rd_player_hp(), rd_player_spells(), rd_quests(), remove_object_curse(), rune_desc(), rune_name(), see_floor_items(), show_file(), spell_append_value_info(), spell_menu_browse(), splashscreen_note(), spoil_artifact(), spoil_obj_desc(), store_purchase(), store_redraw(), store_sell(), sval_menu(), textui_get_count(), try_load(), ui_keymap_create(), update_messages_subwindow(), wiz_display_item(), wiz_statistics(), write_dummy_object_record(), and write_flags().

◆ plog_fmt()

void plog_fmt ( const char *  fmt,
  ... 
)

Vararg interface to plog()

Vararg interface to "plog()", using "format()".

References plog(), and vformat().

Referenced by html_screenshot(), load_sound(), and open_audio_sdl().

◆ quit_fmt()

void quit_fmt ( const char *  fmt,
  ... 
)

◆ strnfcat()

void strnfcat ( char *  str,
size_t  max,
size_t *  end,
const char *  fmt,
  ... 
)

◆ strnfmt()

size_t strnfmt ( char *  buf,
size_t  max,
const char *  fmt,
  ... 
)

Do a vstrnfmt (see above) into a buffer of a given size.

Simple interface to "vstrnfmt()".

References vstrnfmt().

Referenced by adjust_level(), append_random_value_string(), artifact_gen_name(), brand_object(), build_obj_list(), build_score(), cnv_stat(), coords_desc(), deactivate_randart_file(), death_info(), describe_effect(), describe_origin(), display_player_stat_info(), display_scores_aux(), do_cmd_delay(), do_cmd_hp_warn(), do_cmd_inscribe(), do_cmd_keylog(), do_cmd_lazymove_delay(), do_cmd_locate(), do_cmd_note(), do_cmd_wiz_change_aux(), do_cmd_wiz_help(), do_cmd_wiz_jump(), dump_history(), effect_handler_DAMAGE(), get_char(), get_curse_display(), get_item_allow(), get_mon_name(), get_subject(), history_display(), history_find_artifact(), history_lose_artifact(), item_menu_browser(), kind_info(), list_saves(), lookup_symbol(), lore_append_exp(), make_attack_normal(), menu_header(), mon_take_hit(), monster_list_format_section(), nds_load_tile_bmp(), o_xtra_act(), object_desc(), object_list_format_name(), object_list_format_section(), player_pickup_gold(), process_character_pref_files(), project_m_apply_side_effects(), project_monster_handler_FORCE(), project_p(), project_player_handler_FORCE(), prt_ac(), prt_depth(), prt_exp(), prt_gold(), prt_hp(), prt_level(), prt_level_feeling(), prt_sp(), prt_speed(), prt_state(), ranged_helper(), remove_old_dump(), rune_xtra_act(), savefile_save(), savefile_set_name(), set_obj_names(), show_adv_exp(), show_command_list(), show_depth(), show_equip(), show_file(), show_inven(), show_obj(), show_obj_list(), show_speed(), show_splashscreen(), spell_append_value_info(), spell_menu_display(), spell_menu_select(), spoil_mon_desc(), stats_db_bind_rv(), stats_db_open(), store_display_entry(), store_display_frame(), store_purchase(), target_recall_loop_object(), target_set_interactive_aux(), text_lines_to_file(), textui_cmd_ignore_menu(), textui_get_check(), textui_get_quantity(), textui_get_spell(), verify_object(), wiz_create_item_action(), wiz_create_item_subdisplay(), wiz_quantity_item(), wiz_tweak_item(), and wr_description().

◆ vformat()

char* vformat ( const char *  fmt,
va_list  vp 
)

Do a vstrnfmt (see above) into a (growable) static buffer.

Format arguments into a static resizing buffer.

This buffer is usable for very short term formatting of results.

References args, format_buf, format_len, mem_realloc(), mem_zalloc(), VA_COPY, and vstrnfmt().

Referenced by format(), plog_fmt(), put_str_centred(), and quit_fmt().

◆ vformat_kill()

void vformat_kill ( void  )

Free the memory allocated for the format buffer.

References format_buf, and mem_free().

Referenced by cleanup_angband().

◆ vstrnfmt()

size_t vstrnfmt ( char *  buf,
size_t  max,
const char *  fmt,
va_list  vp 
)

Here is some information about the routines in this file.

Format arguments into given bounded-length buffer.

In general, the following routines take a "buffer", a "max length", a "format string", and some "arguments", and use the format string and the arguments to create a (terminated) string in the buffer (using only the first "max length" bytes), and return the "length" of the resulting string, not including the (mandatory) terminator.

The format strings allow the basic "sprintf()" format sequences, though some of them are processed slightly more carefully or portably, as well as a few "special" sequences, including the "capilitization" sequences of "%C" and "%S".

Note that some "limitations" are enforced by the current implementation, for example, no "format sequence" can exceed 100 characters, including any "length" restrictions, and the result of combining and "format sequence" with the relevent "arguments" must not exceed 1000 characters.

These limitations could be fixed by stealing some of the code from, say, "vsprintf()" and placing it into my "vstrnfmt()" function.

Legal format characters: %,b,n,p,c,s,d,i,o,u,X,x,E,e,F,f,G,g,r,v.

Format("%%") Append the literal "%". No legal modifiers.

Format("%n", size_t *np) Save the current length into (*np). No legal modifiers.

Format("%p", void *v) Append the pointer "v" (implementation varies). No legal modifiers.

Format("%E", double r) Format("%F", double r) Format("%G", double r) Format("%e", double r) Format("%f", double r) Format("%g", double r) Append the double "r", in various formats.

Format("%ld", long int i) Append the long integer "i".

Format("%d", int i) Append the integer "i".

Format("%lu", unsigned long int i) Append the unsigned long integer "i".

Format("%u", unsigned int i) Append the unsigned integer "i".

Format("%lo", unsigned long int i) Append the unsigned long integer "i", in octal.

Format("%o", unsigned int i) Append the unsigned integer "i", in octal.

Format("%lX", unsigned long int i) Note – use all capital letters Format("%lx", unsigned long int i) Append the unsigned long integer "i", in hexidecimal.

Format("%X", unsigned int i) Note – use all capital letters Format("%x", unsigned int i) Append the unsigned integer "i", in hexidecimal.

Format("%c", char c) Append the character "c". Do not use the "+" or "0" flags.

Format("%s", const char *s) Append the string "s". Do not use the "+" or "0" flags. Note that a "NULL" value of "s" is converted to the empty string.

Format("%y", type_union *y). Use any of the above patterns; z is interpreted as one of c, d, f, or s in the patterns above, as appropriate for the type of the corresponding argument. (There is currently no way to render a typeunion in octal or hex.)

For examples below, assume "int n = 0; int m = 100; char buf[100];", plus "char *s = NULL;", and unknown values "char *txt; int i;".

For example: "n = strnfmt(buf, -1, "(Max d)", i);" will have a similar effect as "sprintf(buf, "(Max d)", i); n = strlen(buf);".

For example: "(void)strnfmt(buf, 16, "s", txt);" will have a similar effect as "strncpy(buf, txt, 16); buf[15] = '\0';".

For example: "if (strnfmt(buf, 16, "s", txt) < 16) ..." will have a similar effect as "strcpy(buf, txt)" but with bounds checking.

For example: "s = buf; s += vstrnfmt(s, -1, ...); ..." will allow multiple "appends" to "buf" (at the cost of losing the max-length info).

For example: "s = buf; n = vstrnfmt(s+n, 100-n, ...); ..." will allow multiple bounded "appends" to "buf", with constant access to "strlen(buf)".

For example: "format("%-.*s", i, txt)" will produce a string containing the first "i" characters of "txt", left justified. Basic "vararg" format function.

This function takes a buffer, a max byte count, a format string, and a va_list of arguments to the format string, and uses the format string and the arguments to create a string to the buffer. The string is derived from the format string and the arguments in the manner of the "sprintf()" function, but with some extra "format" commands. Note that this function will never use more than the given number of bytes in the buffer, preventing messy invalid memory references. This function then returns the total number of non-null bytes written into the buffer.

Method: Let "str" be the (unlimited) created string, and let "len" be the smaller of "max-1" and "strlen(str)". We copy the first "len" chars of "str" into "buf", place "\0" into buf[len], and return "len".

In English, we do a sprintf() into "buf", a buffer with size "max", and we return the resulting value of "strlen(buf)", but we allow some special format commands, and we are more careful than "sprintf()".

Typically, "max" is in fact the "size" of "buf", and thus represents the "number" of chars in "buf" which are ALLOWED to be used. An alternative definition would have required "buf" to hold at least "max+1" characters, and would have used that extra character only in the case where "buf" was too short for the result. This would give an easy test for "overflow", but a less "obvious" semantics.

Note that if the buffer was "too short" to hold the result, we will always return "max-1", but we also return "max-1" if the buffer was "just long enough". We could have returned "max" if the buffer was too short, not written a null, and forced the programmer to deal with this special case, but I felt that it is better to at least give a "usable" result when the buffer was too long instead of either giving a memory overwrite like "sprintf()" or a non-terminted string like "strncpy()". Note that "strncpy()" also "null-pads" the result.

Note that in most cases "just long enough" is probably "too short".

As of 4.0, we use snprintf (for safety, and to quieten picky compilers)

We should also consider extracting and processing the "width" and other "flags" by hand, it might be more "accurate", and it would allow us to remove the limit (1000 chars) on the result of format sequences.

Also, some sequences, such as "%+d" by hand, do not work on all machines, and could thus be correctly handled here.

Error detection in this routine is not very graceful, in particular, if an error is detected in the format string, we simply "pre-terminate" the given buffer to a length of zero, and return a "length" of zero. The contents of "buf", except for "buf[0]", may then be undefined.

References i, my_strcpy(), and void().

Referenced by bell(), debug(), file_vputf(), msg(), msgt(), panel_line(), strnfcat(), strnfmt(), text_out(), text_out_c(), text_out_e(), textblock_vappend_c(), and vformat().

Variable Documentation

◆ format_buf

char* format_buf = NULL
static

Referenced by vformat(), and vformat_kill().

◆ format_len

size_t format_len = 0
static

Referenced by vformat().