Esempio n. 1
0
/* Tries to use $XDG_CONFIG_HOME/vifm as configuration directory.  Returns
 * non-zero on success, otherwise zero is returned. */
static int
try_xdg_for_conf(void)
{
	LOG_FUNC_ENTER;

	char *config_dir;

	const char *const config_home = env_get("XDG_CONFIG_HOME");
	if(!is_null_or_empty(config_home) && is_path_absolute(config_home))
	{
		config_dir = format_str("%s/vifm", config_home);
	}
	else if(path_exists_at(env_get(HOME_EV), ".config", DEREF))
	{
		config_dir = format_str("%s/.config/vifm", env_get(HOME_EV));
	}
	else
	{
		return 0;
	}

	env_set(VIFM_EV, config_dir);
	free(config_dir);

	return 1;
}
Esempio n. 2
0
File: menu.c Progetto: acklinr/vifm
/* Handles current content of the menu to Vim as quickfix list. */
static void
cmd_v(key_info_t key_info, keys_info_t *keys_info)
{
	int bg;
	const char *vi_cmd;
	FILE *vim_stdin;
	char *cmd;
	int i;
	int qf = 1;

	/* If both first and last lines do not contain colons, treat lines as list of
	 * file names. */
	if(strchr(menu->items[0], ':') == NULL &&
			strchr(menu->items[menu->len - 1], ':') == NULL)
	{
		qf = 0;
	}

	ui_shutdown();
	curr_stats.need_update = UT_FULL;

	vi_cmd = cfg_get_vicmd(&bg);
	if(!qf)
	{
		char *const arg = shell_like_escape("+exe 'bd!|args' "
				"join(map(getline('1','$'),'fnameescape(v:val)'))", 0);
		cmd = format_str("%s %s +argument%d -", vi_cmd, arg, menu->pos + 1);
		free(arg);
	}
	else if(menu->pos == 0)
	{
		/* For some reason +cc1 causes noisy messages on status line, so handle this
		 * case separately. */
		cmd = format_str("%s +cgetbuffer +bd! +cfirst -", vi_cmd);
	}
	else
	{
		cmd = format_str("%s +cgetbuffer +bd! +cfirst +cc%d -", vi_cmd,
				menu->pos + 1);
	}

	vim_stdin = popen(cmd, "w");
	free(cmd);

	if(vim_stdin == NULL)
	{
		recover_after_shellout();
		show_error_msg("Vim QuickFix", "Failed to send list of files to editor.");
		return;
	}

	for(i = 0; i < menu->len; ++i)
	{
		fputs(menu->items[i], vim_stdin);
		putc('\n', vim_stdin);
	}

	pclose(vim_stdin);
	recover_after_shellout();
}
Esempio n. 3
0
/* Composes command to be run using terminal multiplexer.  Returns newly
 * allocated string that should be freed by the caller. */
static char *
gen_term_multiplexer_cmd(const char cmd[], int pause)
{
	char *title_arg;
	char *raw_shell_cmd;
	char *escaped_shell_cmd;
	char *shell_cmd = NULL;

	if(curr_stats.term_multiplexer != TM_TMUX &&
			curr_stats.term_multiplexer != TM_SCREEN)
	{
		assert(0 && "Unexpected active terminal multiplexer value.");
		return NULL;
	}

	title_arg = gen_term_multiplexer_title_arg(cmd);

	raw_shell_cmd = format_str("%s%s", cmd, pause ? PAUSE_STR : "");
	escaped_shell_cmd = shell_like_escape(raw_shell_cmd, 0);

	if(curr_stats.term_multiplexer == TM_TMUX)
	{
		char *const arg = format_str("%s -c %s", cfg.shell, escaped_shell_cmd);
		char *const escaped_arg = shell_like_escape(arg, 0);

		shell_cmd = format_str("tmux new-window %s %s", title_arg, escaped_arg);

		free(escaped_arg);
		free(arg);
	}
	else if(curr_stats.term_multiplexer == TM_SCREEN)
	{
		set_pwd_in_screen(flist_get_dir(curr_view));

		shell_cmd = format_str("screen %s %s -c %s", title_arg, cfg.shell,
				escaped_shell_cmd);
	}
	else
	{
		assert(0 && "Unsupported terminal multiplexer type.");
	}

	free(escaped_shell_cmd);
	free(raw_shell_cmd);
	free(title_arg);

	return shell_cmd;
}
Esempio n. 4
0
/* Draws box and title of the menu. */
static void
draw_menu_frame(const menu_state_t *m)
{
	const size_t title_len = getmaxx(menu_win) - 2*4;
	const char *const suffix = menu_and_view_are_in_sync(m->d, m->view)
	                         ? ""
	                         : replace_home_part(m->d->cwd);
	const char *const at = (suffix[0] == '\0' ? "" : " @ ");
	char *const title = format_str("%s%s%s", m->d->title, at, suffix);

	if(utf8_strsw(title) > title_len)
	{
		const size_t len = utf8_nstrsnlen(title, title_len - 3);
		strcpy(title + len, "...");
	}

	box(menu_win, 0, 0);
	wattron(menu_win, A_BOLD);
	checked_wmove(menu_win, 0, 3);
	wprint(menu_win, " ");
	wprint(menu_win, title);
	wprint(menu_win, " ");
	wattroff(menu_win, A_BOLD);

	free(title);
}
Esempio n. 5
0
/* Writes path configuration file and directories for further usage. */
static void
store_config_paths(void)
{
	LOG_FUNC_ENTER;

	const char *const trash_dir_fmt =
#ifndef _WIN32
			"%%r/.vifm-Trash-%%u,%s/" TRASH ",%%r/.vifm-Trash";
#else
			"%%r/.vifm-Trash,%s/" TRASH;
#endif

	char *fuse_home;
	const char *trash_base = path_exists_at(env_get(VIFM_EV), TRASH, DEREF)
	                       ? cfg.config_dir
	                       : cfg.data_dir;
	const char *base = path_exists(cfg.data_dir, DEREF)
	                 ? cfg.data_dir
	                 : cfg.config_dir;

	snprintf(cfg.home_dir, sizeof(cfg.home_dir), "%s/", env_get(HOME_EV));
	copy_str(cfg.config_dir, sizeof(cfg.config_dir), env_get(VIFM_EV));
	snprintf(cfg.colors_dir, sizeof(cfg.colors_dir), "%s/colors/",
			cfg.config_dir);
	snprintf(cfg.trash_dir, sizeof(cfg.trash_dir), trash_dir_fmt, trash_base);
	snprintf(cfg.log_file, sizeof(cfg.log_file), "%s/" LOG, base);

	fuse_home = format_str("%s/fuse/", base);
	(void)cfg_set_fuse_home(fuse_home);
	free(fuse_home);
}
Esempio n. 6
0
void disp_tm_edit(void * edit_data)
{
   struct edit_ctrl * edit_ptr;
   struct tm * tm_buf;
   char str[32];
   int x, y;
   int fwidth, fheight;
   static int prev_pos = 0;
   time_t t;
   
   edit_ptr = (struct edit_ctrl *)edit_data;
   tm_buf   = (struct tm *)edit_ptr->buf;
   
   format_str(str, 32, "%02u/%02u/%02u %02u:%02u", tm_buf->tm_mday, tm_buf->tm_mon + 1, getyear2(tm_buf->tm_year), tm_buf->tm_hour, tm_buf->tm_min);

   x = edit_ptr->x;
   y = edit_ptr->y;
   fwidth  = fh[edit_ptr->font]->width;
   fheight = fh[edit_ptr->font]->height;
   
   OLED_puts(x , y, 0xff, edit_ptr->font, str);
   x += tm_get_pointer_pos(prev_pos) * fwidth;
   y += fheight;
   OLED_clr(x, y, fwidth, fheight);
   prev_pos = edit_ptr->buf_pos;
   x  = edit_ptr->x + tm_get_pointer_pos(prev_pos) * fwidth;
   OLED_puts(x , y, 0xff, edit_ptr->font, "^");
   /*
   t = mktime2(&tm4edit);
   format_str(str, 32, "%ld, %llx", t, (unsigned long long)t * 1000);
   OLED_puts(0, 5 * 9,  0xff, edit_ptr->font, str);
   */
}
Esempio n. 7
0
File: menu.c Progetto: cfillion/vifm
void
menu_morph_into_cmdline(CmdLineSubmode submode, const char input[],
		int external)
{
	/* input might point to part of menu data. */
	char *input_copy;

	if(input[0] == '\0')
	{
		show_error_msg("Command insertion", "Ignoring empty command");
		return;
	}

	input_copy = external ? format_str("!%s", input) : strdup(input);
	if(input_copy == NULL)
	{
		show_error_msg("Error", "Not enough memory");
		return;
	}

	leave_menu_mode(0);
	enter_cmdline_mode(submode, input_copy, NULL);

	free(input_copy);
}
Esempio n. 8
0
void
ui_stat_draw_popup_line(WINDOW *win, const char item[], const char descr[],
		size_t max_width)
{
	char *left, *right, *line;
	const size_t text_width = utf8_strsw(item);
	const size_t win_width = getmaxx(win);
	const int align_columns = (max_width <= win_width/4);
	const char *const fmt = align_columns ? "%-*s  %-*s" : "%-*s  %*s";
	size_t width_left;
	size_t item_width;

	if(text_width >= win_width)
	{
		char *const whole = right_ellipsis(item, win_width, curr_stats.ellipsis);
		wprint(win, whole);
		free(whole);
		return;
	}

	left = right_ellipsis(item, win_width - 3, curr_stats.ellipsis);

	item_width = align_columns ? max_width : utf8_strsw(left);
	width_left = win_width - 2 - MAX(item_width, utf8_strsw(left));

	right = right_ellipsis(descr, width_left, curr_stats.ellipsis);

	line = format_str(fmt, (int)item_width, left, (int)width_left, right);
	free(left);
	free(right);

	wprint(win, line);

	free(line);
}
Esempio n. 9
0
gmux_t *
gmux_create(const char name[])
{
	gmux_t *const gmux = malloc(sizeof(*gmux));
	if(gmux == NULL)
	{
		return NULL;
	}

	gmux->name = format_str("Local\\%s-gmux", name);
	if(gmux->name == NULL)
	{
		free(gmux);
		return NULL;
	}

	gmux->handle = CreateMutex(NULL, FALSE, gmux->name);
	if(gmux->handle == NULL)
	{
		free(gmux->name);
		free(gmux);
		return NULL;
	}

	return gmux;
}
Esempio n. 10
0
int
show_trashes_menu(view_t *view, int calc_size)
{
	char **trashes;
	int ntrashes;
	int i;

	static menu_data_t m;
	menus_init_data(&m, view,
			format_str("%sNon-empty trash directories", calc_size ? "[  size] " : ""),
			strdup("No non-empty trash directories found"));

	m.execute_handler = &execute_trashes_cb;
	m.key_handler = &trashes_khandler;
	m.extra_data = calc_size;

	trashes = list_trashes(&ntrashes);

	show_progress(NULL, 0);
	for(i = 0; i < ntrashes; i++)
	{
		char *const item = format_item(trashes[i], calc_size);
		m.len = put_into_string_array(&m.items, m.len, item);
	}

	free_string_array(trashes, ntrashes);

	return menus_enter(m.state, view);
}
Esempio n. 11
0
/* Configures environment variables before shellout.  Should be used in pair
 * with cleanup_shellout_env(). */
static void
setup_shellout_env(void)
{
	const char *mount_file;
	const char *term_multiplexer_fmt;
	char *escaped_path;
	char *cmd;

	/* Need to use internal value instead of getcwd() for a symlink directory. */
	env_set("PWD", curr_view->curr_dir);

	mount_file = fuse_get_mount_file(curr_view->curr_dir);
	if(mount_file == NULL)
	{
		env_remove(FUSE_FILE_ENVVAR);
		return;
	}

	env_set(FUSE_FILE_ENVVAR, mount_file);

	switch(curr_stats.term_multiplexer)
	{
		case TM_TMUX:   term_multiplexer_fmt = "tmux set-environment %s %s"; break;
		case TM_SCREEN: term_multiplexer_fmt = "screen -X setenv %s %s"; break;

		default:
			return;
	}

	escaped_path = shell_like_escape(mount_file, 0);
	cmd = format_str(term_multiplexer_fmt, FUSE_FILE_ENVVAR, escaped_path);
	(void)vifm_system(cmd);
	free(cmd);
	free(escaped_path);
}
Esempio n. 12
0
int
show_fileviewers_menu(FileView *view, const char fname[])
{
	static menu_info m;

	assoc_records_t file_viewers;

	init_menu_info(&m, format_str("Viewers that match %s", fname),
			format_str("No viewers match %s", fname));

	file_viewers = ft_get_all_viewers(fname);
	fill_menu_from_records(&m, &file_viewers);
	ft_assoc_records_free(&file_viewers);

	return display_menu(&m, view);
}
Esempio n. 13
0
File: path.c Progetto: jubalh/vifm
/* Tries to expands tilde in the front of the path.  Returns the path or newly
 * allocated string without tilde. */
static char *
try_replace_tilde(const char path[])
{
#ifndef _WIN32
	char name[NAME_MAX];
	const char *p;
	char *result;
	struct passwd *pw;
#endif

	if(path[0] != '~')
	{
		return (char *)path;
	}

	if(path[1] == '\0' || path[1] == '/')
	{
		char *const result = format_str("%s%s", cfg.home_dir,
				(path[1] == '/') ? (path + 2) : "");
		return result;
	}

#ifndef _WIN32
	if((p = strchr(path, '/')) == NULL)
	{
		p = path + strlen(path);
		copy_str(name, sizeof(name), path + 1);
	}
	else
	{
		snprintf(name, p - (path + 1) + 1, "%s", path + 1);
		p++;
	}

	if((pw = getpwnam(name)) == NULL)
	{
		return (char *)path;
	}

	chosp(pw->pw_dir);
	result = format_str("%s/%s", pw->pw_dir, p);

	return result;
#else
	return (char *)path;
#endif
}
Esempio n. 14
0
/* Removes all files inside given trash directory (even those that this instance
 * of vifm is not aware of). */
static void
empty_trash_dir(const char trash_dir[])
{
	char *const task_desc = format_str("Empty trash: %s", trash_dir);
	char *const op_desc = format_str("Emptying %s", replace_home_part(trash_dir));

	char *const trash_dir_copy = strdup(trash_dir);

	if(bg_execute(task_desc, op_desc, BG_UNDEFINED_TOTAL, 1, &empty_trash_in_bg,
			trash_dir_copy) != 0)
	{
		free(trash_dir_copy);
	}

	free(op_desc);
	free(task_desc);
}
	TEST_F(OutputFormatterTest, OtherCharacterAfterBackslashInFormatString) {
		std::wstring format_str(L"%p\\d %p");
		OutputFormatter formater(&input, format_str);
		auto res = formater.Format();

		EXPECT_TRUE((*res)[0] == std::wstring(L"my_file1\\d my_file1"));
		EXPECT_TRUE((*res)[1] == std::wstring(L"my_file2\\d my_file2"));
	}
	TEST_F(OutputFormatterTest, HorizontalTabInFormatString) {
		std::wstring format_str(L"%p\\t%p");
		OutputFormatter formater(&input, format_str);
		auto res = formater.Format();

		EXPECT_TRUE((*res)[0] == std::wstring(L"my_file1	my_file1"));
		EXPECT_TRUE((*res)[1] == std::wstring(L"my_file2	my_file2"));
	}
	TEST_F(OutputFormatterTest, EscapedBackslashInFormatString) {
		std::wstring format_str(L"%p\\\\%p\\\\");
		OutputFormatter formater(&input, format_str);
		auto res = formater.Format();

		EXPECT_TRUE((*res)[0] == std::wstring(L"my_file1\\my_file1\\"));
		EXPECT_TRUE((*res)[1] == std::wstring(L"my_file2\\my_file2\\"));
	}
Esempio n. 18
0
/* Formats a command to edit selected files of the current view in an editor.
 * Returns a newly allocated string, which should be freed by the caller. */
TSTATIC char *
format_edit_selection_cmd(int *bg)
{
	char *const files = expand_macros("%f", NULL, NULL, 1);
	char *const cmd = format_str("%s %s", cfg_get_vicmd(bg), files);
	free(files);
	return cmd;
}
Esempio n. 19
0
int
show_fileprograms_menu(FileView *view, const char fname[])
{
	static menu_info m;

	assoc_records_t file_programs;

	init_menu_info(&m, FILEPROGRAMS_MENU,
			format_str("No programs match %s", fname));

	m.title = format_str(" Programs that match %s ", fname);

	file_programs = ft_get_all_programs(fname);
	fill_menu_from_records(&m, &file_programs);
	ft_assoc_records_free(&file_programs);

	return display_menu(&m, view);
}
Esempio n. 20
0
string write_roster_players(string roster_filename, const RosterPlayerArray& players_arr)
{
    ofstream rosterfile(roster_filename.c_str());

    if (!rosterfile)
        return format_str("Failed to open roster %s", roster_filename.c_str());

    rosterfile << "Name         Age Nat Prs St Tk Ps Sh Sm Ag KAb TAb PAb SAb Gam Sav Ktk Kps Sht Gls Ass  DP Inj Sus Fit\n";
    rosterfile << "------------------------------------------------------------------------------------------------------\n";

    for (RosterPlayerConstIterator player = players_arr.begin(); player != players_arr.end(); ++player)
    {
        rosterfile << format_str("%-13s%3d%4s%4s%3d%3d%3d%3d%3d%3d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d\n",
                player->name.c_str(),
                player->age,
                player->nationality.c_str(),
                player->pref_side.c_str(),
                player->st,
                player->tk,
                player->ps,
                player->sh,
                player->stamina,
                player->ag,
                player->st_ab,
                player->tk_ab,
                player->ps_ab,
                player->sh_ab,
                player->games,
                player->saves,
                player->tackles,
                player->keypasses,
                player->shots,
                player->goals,
                player->assists,
                player->dp,
                player->injury,
                player->suspension,
                player->fitness);
    }

    rosterfile << endl;
	return "";
}
Esempio n. 21
0
/* Changes $PWD in running GNU/screen session to the specified path.  Needed for
 * symlink directories and sshfs mounts. */
static void
set_pwd_in_screen(const char path[])
{
	char *const escaped_dir = shell_like_escape(path, 0);
	char *const set_pwd = format_str("screen -X setenv PWD %s", escaped_dir);

	(void)vifm_system(set_pwd);

	free(set_pwd);
	free(escaped_dir);
}
Esempio n. 22
0
/* Replaces *str with a copy of the with string extended by the suffix.  *str
 * can be NULL in which case it's treated as empty string, equal to the with
 * (then function does nothing).  Returns non-zero if memory allocation
 * failed. */
static void
append_to_string(char **str, const char suffix[])
{
	const char *const non_null_str = (*str == NULL) ? "" : *str;
	char *const appended_str = format_str("%s%s", non_null_str, suffix);
	if(appended_str != NULL)
	{
		free(*str);
		*str = appended_str;
	}
}
Esempio n. 23
0
/* Collects files under specified file system tree. */
static void
list_files_recursively(const char path[], int skip_dot_files, strlist_t *list)
{
	int i;

	/* Obtain sorted list of files. */
	int len;
	char **lst = list_sorted_files(path, &len);
	if(len < 0)
	{
		return;
	}

	/* Visit all subdirectories ignoring symbolic links to directories. */
	for(i = 0; i < len && !ui_cancellation_requested(); ++i)
	{
		char *full_path;
		if(skip_dot_files && lst[i][0] == '.')
		{
			update_string(&lst[i], NULL);
			continue;
		}

		full_path = format_str("%s/%s", path, lst[i]);
		if(is_dir(full_path))
		{
			if(!is_symlink(full_path))
			{
				list_files_recursively(full_path, skip_dot_files, list);
			}
			free(full_path);
			update_string(&lst[i], NULL);
		}
		else
		{
			free(lst[i]);
			lst[i] = full_path;
		}

		show_progress("Listing...", 1000);
	}

	/* Append files. */
	for(i = 0; i < len; ++i)
	{
		if(lst[i] != NULL)
		{
			list->nitems = put_into_string_array(&list->items, list->nitems, lst[i]);
		}
	}

	free(lst);
}
Esempio n. 24
0
File: count.c Progetto: KryDos/vifm
static void
test_max_count_is_handled_correctly(void)
{
	char *const keys = format_str("%udd", INT_MAX);
	wchar_t *const keysw = to_wide(keys);

	assert_false(IS_KEYS_RET_CODE(execute_keys(keysw)));
	assert_int_equal(INT_MAX, last_command_count);

	free(keysw);
	free(keys);
}
Esempio n. 25
0
char *
fast_run_complete(const char cmd[])
{
	char *result = NULL;
	const char *args;
	char command[NAME_MAX];
	char *completed;

	args = extract_cmd_name(cmd, 0, sizeof(command), command);

	if(is_path_absolute(command))
	{
		return strdup(cmd);
	}

	vle_compl_reset();
	complete_command_name(command);
	vle_compl_unite_groups();
	completed = vle_compl_next();

	if(vle_compl_get_count() > 2)
	{
		int c = vle_compl_get_count() - 1;
		while(c-- > 0)
		{
			if(stroscmp(command, completed) == 0)
			{
				result = strdup(cmd);
				break;
			}
			else
			{
				free(completed);
				completed = vle_compl_next();
			}
		}

		if(result == NULL)
		{
			status_bar_error("Command beginning is ambiguous");
		}
	}
	else
	{
		free(completed);
		completed = vle_compl_next();
		result = format_str("%s %s", completed, args);
	}
	free(completed);

	return result;
}
Esempio n. 26
0
File: info.c Progetto: cfillion/vifm
/* Performs conversions on files in trash required for partial backward
 * compatibility.  Returns newly allocated string that should be freed by the
 * caller. */
static char *
convert_old_trash_path(const char trash_path[])
{
	if(!is_path_absolute(trash_path) && is_dir_writable(cfg.trash_dir))
	{
		char *const full_path = format_str("%s/%s", cfg.trash_dir, trash_path);
		if(path_exists(full_path, DEREF))
		{
			return full_path;
		}
		free(full_path);
	}
	return strdup(trash_path);
}
Esempio n. 27
0
char *
describe_abbrev(const wchar_t lhs[], const wchar_t rhs[], int no_remap,
		int offset)
{
	enum { LHS_MIN_WIDTH = 13 };
	const char map_mark = no_remap ? '*' : ' ';

	char *const keys = wstr_to_spec(rhs);
	char *const descr = format_str("%-*ls %3c    %s", offset + LHS_MIN_WIDTH, lhs,
			map_mark, keys);
	free(keys);

	return descr;
}
Esempio n. 28
0
/* does real job on setting terminal title */
static void
set_terminal_title(const char *path)
{
#ifdef _WIN32
	wchar_t buf[2048];
	vifm_swprintf(buf, ARRAY_LEN(buf), L"%" WPRINTF_MBSTR L" - VIFM", path);
	SetConsoleTitleW(buf);
#else
	char *const title = format_str("\033]2;%s - VIFM\007", path);
	putp(title);
	fflush(stdout);
	free(title);
#endif
}
Esempio n. 29
0
/* Does all the real work on setting terminal title. */
static void
set_terminal_title(const char path[])
{
#ifdef _WIN32
	wchar_t *utf16;
	char title[2048];
	snprintf(title, sizeof(title), "%s - VIFM", path);

	utf16 = utf8_to_utf16(title);
	SetConsoleTitleW(utf16);
	free(utf16);
#else
	char *const title = format_str("\033]2;%s - VIFM\007", path);
	putp(title);
	fflush(stdout);
	free(title);
#endif
}
Esempio n. 30
0
/* Makes fingerprint of file contents (all or part of it of fixed size).
 * Returns the fingerprint as a string, which is empty or NULL on error. */
static char *
get_contents_fingerprint(const char path[], const dir_entry_t *entry)
{
#if INTPTR_MAX == INT64_MAX
#define XX_BITS 64
#else
#define XX_BITS 32
#endif
#define XX__(name, bits) XXH ## bits ## _ ## name
#define XX_(name, bits) XX__(name, bits)
#define XX(name) XX_(name, XX_BITS)

	XX(state_t) st;
	char block[BLOCK_SIZE];
	size_t to_read = PREFIX_SIZE;
	FILE *in = os_fopen(path, "rb");
	if(in == NULL)
	{
		return strdup("");
	}

	XX(reset)(&st, 0U);
	while(to_read != 0U)
	{
		const size_t portion = MIN(sizeof(block), to_read);
		const size_t nread = fread(&block, 1, portion, in);
		if(nread == 0U)
		{
			break;
		}

		XX(update)(&st, block, nread);
		to_read -= nread;
	}
	fclose(in);

	return format_str("%" PRINTF_ULL "|%" PRINTF_ULL,
			(unsigned long long)entry->size, (unsigned long long)XX(digest)(&st));

#undef XX_BITS
#undef XX__
#undef XX_
#undef XX
}