Sophie

Sophie

distrib > Mandriva > 2009.0 > i586 > by-pkgid > c0f387da87747a17f501c57ce0fdae14 > files > 2

lirc-remotes-0.8.3-0.20080704.3mdv2009.0.src.rpm


// gcc -Wall -o lirc-fixup-keys lirc-fixup-keys.c `pkg-config --libs --cflags glib-2.0`

#include <glib.h>
#include <string.h>

#define BEGIN_CODES_STR "begin codes"

GHashTable *hash = NULL;

static gboolean
load_subs (const char *path)
{
	GMappedFile *map;
	char *contents, **lines;
	guint i;

	map = g_mapped_file_new (path, FALSE, NULL);
	if (map == NULL)
		return FALSE;

	contents = g_strdup (g_mapped_file_get_contents (map));
	g_mapped_file_free (map);

	lines = g_strsplit (contents, "\n", -1);
	g_free (contents);

	hash = g_hash_table_new_full (g_str_hash,
				      g_str_equal,
				      g_free,
				      g_free);

	for (i = 0; lines[i] != NULL; i++) {
		char **items;
		char *orig, *target;

		items = g_strsplit (lines[i], "|", -1);
		if (items[0] == NULL || items[1] == NULL)
			break;
		orig = g_strstrip (items[0]);
		target = g_strstrip (items[1]);

		if (strcmp (target, "TO_BE_DISCUSSED") != 0
		    && strcmp (target, "TO_BE_SUPPRESSED") != 0) {
		    	g_hash_table_insert (hash, g_strdup (orig), g_strdup (target));
		}

		g_strfreev (items);
	}

	g_strfreev (lines);

	return TRUE;
}

static void
cleanup_subs (void)
{
	g_hash_table_destroy (hash);
	hash = NULL;
}

static gboolean
eval_cb (const GMatchInfo *match_info,
	 GString *result,
	 gpointer user_data)
{
	char *match, *new, *s;

	/* We don't want to lose the formatting */
	s = g_match_info_fetch (match_info, 1);
	g_string_append (result, s);

	match = g_match_info_fetch (match_info, 2);
	new = g_hash_table_lookup (hash, match);
	g_string_append (result, new ? new : match);
	g_free (match);

	return FALSE;
}

static gboolean
split_defs (const char *contents, char **beginning, char **codes, char **end)
{
	char **p, **q;

	//FIXME more checks on nils
	p = g_strsplit (contents, "begin codes", 2);
	if (p[0] == NULL || p[1] == NULL) {
		g_strfreev (p);
		return FALSE;
	}
	*beginning = g_strdup (p[0]);
	q = g_strsplit (p[1], "end codes", 2);
	*codes = g_strdup (q[0]);
	*end = g_strdup (q[1]);

	g_strfreev (q);
	g_strfreev (p);

	return TRUE;
}

static gboolean
subs_file (const char *filename)
{
	char *contents;
	char *beginning, *codes, *end;
	char **lines;
	guint i;
	GString *result;
	GRegex *e;

	if (g_file_get_contents (filename, &contents, NULL, NULL) == FALSE)
		return FALSE;

	if (split_defs (contents, &beginning, &codes, &end) == FALSE) {
		g_free (contents);
		return FALSE;
	}
	g_free (contents);

	result = g_string_new (beginning);
	g_free (beginning);
	g_string_append (result, "begin codes");
	lines = g_strsplit (codes, "\n", -1);
	g_free (codes);

	e = g_regex_new ("^([\\t ]+)(\\S+)", 0, 0, NULL);

	for (i = 0; lines[i] != NULL; i++) {
		GError *err = NULL;
		char *new;

		if (i != 0)
			g_string_append_c (result, '\n');

		new = g_regex_replace_eval (e, lines[i], -1, 0, 0, eval_cb, NULL, &err);
		if (new == NULL) {
			g_message ("FAIL! %s", err->message);
			g_error_free (err);
			return FALSE;
		}
		g_string_append (result, new);
		g_free (new);
	}
	g_strfreev (lines);
	g_regex_unref (e);

	g_string_append (result, "end codes");
	g_string_append (result, end);
	g_free (end);

#if 0
	g_print ("%s", result->str);
#else
	if (g_file_set_contents (filename, result->str, -1, NULL) == FALSE) {
		g_string_free (result, TRUE);
		return FALSE;
	}
#endif
	g_string_free (result, TRUE);

	return TRUE;
}

static gboolean
parse_subdir (const char *subdir)
{
	GDir *dir;
	const char *name;
	char *fullpath;

	dir = g_dir_open (subdir, 0, NULL);
	if (dir == NULL)
		return FALSE;

	name = g_dir_read_name (dir);
	do {
		/* At the top-level, we're only interested in directories */
		fullpath = g_build_filename (subdir, name, NULL);
		if (g_file_test (fullpath, G_FILE_TEST_IS_REGULAR) == FALSE) {
			g_free (fullpath);
			name = g_dir_read_name (dir);
			if (name == NULL)
				break;
			continue;
		}

		if (subs_file (fullpath) == FALSE)
			g_message ("ignored %s", fullpath);

		g_free (fullpath);
		name = g_dir_read_name (dir);
	} while (name != NULL);

	g_dir_close (dir);

	return TRUE;
}

static gboolean
parse_remotes (const char *path)
{
	GDir *dir;
	const char *name;
	char *fullpath;

	//FIXME for debugging
	if (g_file_test (path, G_FILE_TEST_IS_REGULAR) != FALSE)
		return subs_file (path);

	/* Now the real thing */
	dir = g_dir_open (path, 0, NULL);
	if (dir == NULL)
		return FALSE;

	name = g_dir_read_name (dir);
	do {
		/* At the top-level, we're only interested in directories */
		fullpath = g_build_filename (path, name, NULL);
		if (g_file_test (fullpath, G_FILE_TEST_IS_DIR) == FALSE
		    || strcmp (name, "CVS") == 0) {
			g_free (fullpath);
			name = g_dir_read_name (dir);
			if (name == NULL)
				break;
			continue;
		}

		if (parse_subdir (fullpath) == FALSE) {
			g_free (fullpath);
			g_dir_close (dir);
			return FALSE;
		}

		g_free (fullpath);
		name = g_dir_read_name (dir);
	} while (name != NULL);

	g_dir_close (dir);

	return TRUE;
}

static void
set_warnings (void)
{
	GLogLevelFlags fatal_mask;

	fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
	fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
	g_log_set_always_fatal (fatal_mask);
}

int main (int argc, char **argv)
{
	if (argc != 3) {
		g_warning ("Usage: %s <nns.txt path> <directory to remote files>", argv[0]);
		return 1;
	}

	set_warnings ();

	if (load_subs (argv[1]) == FALSE) {
		g_warning ("Failed to parse %s", argv[1]);
		return 1;
	}

	if (parse_remotes (argv[2]) == FALSE) {
		g_warning ("Failed to work on %s", argv[2]);
		return 1;
	}

	cleanup_subs ();

	return 0;
}