/* $Id$
 *
 *  Utilitiy functions to log assertions messages.
 *
 * Copyright (C) 2008-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#include "log.h"
#include <stdbool.h>
#include "glue-log.h"
#include "glue-main.h"
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <assert.h>
#include "mangle_names.h"

/* FIXME ripped from glue-main */
#define TIME_HZ		(1ULL << 32)

static void
log_begin(
	const struct glue_vhdl_cb *callbacks,
	const char *lvl_msg, 
	const char *path_name
)
{
	struct timeval tv;
	struct tm *tm;
	int ret;
	static char demangled[2048];

	tv.tv_sec = callbacks->time_virt() / TIME_HZ;
	tv.tv_usec = ((callbacks->time_virt() % TIME_HZ) * 1000000) / TIME_HZ;

	/* Convert the time into a little more useful structure. */
	tm = localtime(&tv.tv_sec);
	if (tm == NULL) {
		perror("Couldn't break up system time");
		exit(1);
	}
	ret = demangle_name(path_name, demangled, sizeof(demangled));
	assert(ret >= 0);

	/* Generate the Oracle timestamp. */
	ret = fprintf(stdout, "%s: %.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.6d %s in ",
		lvl_msg,
		tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
		tm->tm_hour, tm->tm_min, tm->tm_sec, 
		(unsigned int)tv.tv_usec,
		demangled
		);

	if (ret < 0) {
		perror("Timestamp formatting error");
		exit(1);
	}
}
#undef TIME_HZ

void
log_vhdl(
	const struct glue_vhdl_cb *callbacks,
	int level, 
	const char *path_name, 
	char c
)
{
	bool log_start = true;
	const char *severity;

	switch (level) {
	case -1:
		log_start = false;
		break;

	case 0:
		severity = "NOTE";
		break;

	case 1:
		severity = "WARNING";
		break;

	case 2:
		severity = "ERROR";
		break;

	case 3:
		severity = "FAILURE";
		break;

	default:
		callbacks->log(FAUHDLI_LOG_ERROR, "fauhdli", __func__,
			"Illegal severity level %d\n", level);
		severity = "NOTE";
		break;
	}

	if (log_start) {
		log_begin(callbacks, severity, path_name);
	}

	fprintf(stdout, "%c", c);
	if (c == '\n') {
		int ret = fflush(stdout);
		assert(ret == 0);
	}
}

