<commit_before>/*-------------------------------------------------------------------------
 *
 * path.c
 *	  portable path handling routines
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $PostgreSQL: pgsql/src/port/path.c,v 1.12 2004/05/25 01:00:30 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */

#include "c.h"

#include <ctype.h>

#include "pg_config_paths.h"


#ifndef WIN32
#define	ISSEP(ch)	((ch) == '/')
#else
#define	ISSEP(ch)	((ch) == '/' || (ch) == '\\')
#endif

static bool relative_path(const char *path1, const char *path2);
static void trim_directory(char *path);
static void trim_trailing_separator(char *path);

/* Move to last of consecutive separators or to null byte */
#define MOVE_TO_SEP_END(p) \
{ \
	while (ISSEP((p)[0]) && (ISSEP((p)[1]) || !(p)[1])) \
		(p)++; \
}


/*
 *	first_path_separator
 */
char *
first_path_separator(const char *filename)
{
	char	   *p;

	for (p = (char *)filename; *p; p++)
		if (ISSEP(*p))
			return p;
	return NULL;
}


/*
 *	last_path_separator
 */
char *
last_path_separator(const char *filename)
{
	char	   *p, *ret = NULL;

	for (p = (char *)filename; *p; p++)
		if (ISSEP(*p))
			ret = p;
	return ret;
}


/*
 * make all paths look like unix, with forward slashes
 * also strip any trailing slash.
 *
 * The Windows command processor will accept suitably quoted paths
 * with forward slashes, but barfs badly with mixed forward and back
 * slashes. Removing the trailing slash on a path means we never get
 * ugly double slashes.  Don't remove a leading slash, though.
 */
void
canonicalize_path(char *path)
{
#ifdef WIN32
	char	   *p;

	for (p = path; *p; p++)
	{
		if (*p == '\\')
			*p = '/';
	}
#endif

	trim_trailing_separator(path);
}


/*
 * Extracts the actual name of the program as called.
 */
const char *
get_progname(const char *argv0)
{
	if (!last_path_separator(argv0))
		return argv0;
	else
		return last_path_separator(argv0) + 1;
}


/*
 *	get_share_path
 */
void
get_share_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, PGSHAREDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);	/* trim off binary */
		trim_directory(path);	/* trim off /bin */
		snprintf(ret_path, MAXPGPATH, "%s/share", path);
	}
	else
		StrNCpy(ret_path, PGSHAREDIR, MAXPGPATH);
}



/*
 *	get_etc_path
 */
void
get_etc_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, SYSCONFDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/etc", path);
	}
	else
		StrNCpy(ret_path, SYSCONFDIR, MAXPGPATH);
}



/*
 *	get_include_path
 */
void
get_include_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, INCLUDEDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/include", path);
	}
	else
		StrNCpy(ret_path, INCLUDEDIR, MAXPGPATH);
}



/*
 *	get_pkginclude_path
 */
void
get_pkginclude_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, PKGINCLUDEDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/include", path);
	}
	else
		StrNCpy(ret_path, PKGINCLUDEDIR, MAXPGPATH);
}



/*
 *	get_pkglib_path
 *
 *	Return library path, either relative to /bin or hardcoded
 */
void
get_pkglib_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, PKGLIBDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/lib", path);
	}
	else
		StrNCpy(ret_path, PKGLIBDIR, MAXPGPATH);
}



/*
 *	get_locale_path
 *
 *	Return locale path, either relative to /bin or hardcoded
 */
void
get_locale_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, LOCALEDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/share/locale", path);
	}
	else
		StrNCpy(ret_path, LOCALEDIR, MAXPGPATH);
}



/*
 *	set_pglocale
 *
 *	Set application-specific locale
 *
 *	This function takes an argv[0] rather than a full path.
 */
void
set_pglocale(const char *argv0, const char *app)
{
#ifdef ENABLE_NLS
	char path[MAXPGPATH];
	char my_exec_path[MAXPGPATH];

	setlocale(LC_ALL, "");
	if (find_my_exec(argv0, my_exec_path) < 0)
		return;
		
	get_locale_path(argv0, path);
	bindtextdomain(app, path);
	textdomain(app);
#endif
}



/*
 *	relative_path<commit_msg>Skip settting LC_ALL in the backend.<commit_after>/*-------------------------------------------------------------------------
 *
 * path.c
 *	  portable path handling routines
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $PostgreSQL: pgsql/src/port/path.c,v 1.13 2004/05/25 01:42:08 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */

#include "c.h"

#include <ctype.h>

#include "pg_config_paths.h"


#ifndef WIN32
#define	ISSEP(ch)	((ch) == '/')
#else
#define	ISSEP(ch)	((ch) == '/' || (ch) == '\\')
#endif

static bool relative_path(const char *path1, const char *path2);
static void trim_directory(char *path);
static void trim_trailing_separator(char *path);

/* Move to last of consecutive separators or to null byte */
#define MOVE_TO_SEP_END(p) \
{ \
	while (ISSEP((p)[0]) && (ISSEP((p)[1]) || !(p)[1])) \
		(p)++; \
}


/*
 *	first_path_separator
 */
char *
first_path_separator(const char *filename)
{
	char	   *p;

	for (p = (char *)filename; *p; p++)
		if (ISSEP(*p))
			return p;
	return NULL;
}


/*
 *	last_path_separator
 */
char *
last_path_separator(const char *filename)
{
	char	   *p, *ret = NULL;

	for (p = (char *)filename; *p; p++)
		if (ISSEP(*p))
			ret = p;
	return ret;
}


/*
 * make all paths look like unix, with forward slashes
 * also strip any trailing slash.
 *
 * The Windows command processor will accept suitably quoted paths
 * with forward slashes, but barfs badly with mixed forward and back
 * slashes. Removing the trailing slash on a path means we never get
 * ugly double slashes.  Don't remove a leading slash, though.
 */
void
canonicalize_path(char *path)
{
#ifdef WIN32
	char	   *p;

	for (p = path; *p; p++)
	{
		if (*p == '\\')
			*p = '/';
	}
#endif

	trim_trailing_separator(path);
}


/*
 * Extracts the actual name of the program as called.
 */
const char *
get_progname(const char *argv0)
{
	if (!last_path_separator(argv0))
		return argv0;
	else
		return last_path_separator(argv0) + 1;
}


/*
 *	get_share_path
 */
void
get_share_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, PGSHAREDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);	/* trim off binary */
		trim_directory(path);	/* trim off /bin */
		snprintf(ret_path, MAXPGPATH, "%s/share", path);
	}
	else
		StrNCpy(ret_path, PGSHAREDIR, MAXPGPATH);
}



/*
 *	get_etc_path
 */
void
get_etc_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, SYSCONFDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/etc", path);
	}
	else
		StrNCpy(ret_path, SYSCONFDIR, MAXPGPATH);
}



/*
 *	get_include_path
 */
void
get_include_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, INCLUDEDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/include", path);
	}
	else
		StrNCpy(ret_path, INCLUDEDIR, MAXPGPATH);
}



/*
 *	get_pkginclude_path
 */
void
get_pkginclude_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, PKGINCLUDEDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/include", path);
	}
	else
		StrNCpy(ret_path, PKGINCLUDEDIR, MAXPGPATH);
}



/*
 *	get_pkglib_path
 *
 *	Return library path, either relative to /bin or hardcoded
 */
void
get_pkglib_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, PKGLIBDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/lib", path);
	}
	else
		StrNCpy(ret_path, PKGLIBDIR, MAXPGPATH);
}



/*
 *	get_locale_path
 *
 *	Return locale path, either relative to /bin or hardcoded
 */
void
get_locale_path(const char *my_exec_path, char *ret_path)
{
	char path[MAXPGPATH];
	
	if (relative_path(PGBINDIR, LOCALEDIR))
	{
		StrNCpy(path, my_exec_path, MAXPGPATH);
		trim_directory(path);
		trim_directory(path);
		snprintf(ret_path, MAXPGPATH, "%s/share/locale", path);
	}
	else
		StrNCpy(ret_path, LOCALEDIR, MAXPGPATH);
}



/*
 *	set_pglocale
 *
 *	Set application-specific locale
 *
 *	This function takes an argv[0] rather than a full path.
 */
void
set_pglocale(const char *argv0, const char *app)
{
#ifdef ENABLE_NLS
	char path[MAXPGPATH];
	char my_exec_path[MAXPGPATH];

	/* don't set LC_ALL in the backend */
	if (strcmp(app, "postgres") != 0)
		setlocale(LC_ALL, "");

	if (find_my_exec(argv0, my_exec_path) < 0)
		return;
		
	get_locale_path(argv0, path);
	bindtextdomain(app, path);
	textdomain(app);
#endif
}



/*
 *	relative_path
{'fraction_non_alphanumeric': 0.1630688152427283, 'fraction_numerical': 0.009830748961183744, 'mean_word_length': 3.699047619047619, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6462231', 'n_tokens_mistral': 4006, 'n_tokens_neox': 3765, 'n_words': 874}