git @ Cat's Eye Technologies Kosheri / master src / report.c
master

Tree @master (Download .tar.gz)

report.c @masterraw · history · blame

/*
 * report.c
 * Error/warning reporter.
 * $Id: report.c 139 2008-07-16 09:56:31Z catseye $
 */

#include <stdarg.h>

#include "lib.h"

#include "process.h"
#include "stream.h"
#include "file.h"

#include "render.h"

#include "report.h"

struct reporter {
        int		 finished;
        int		 verbose;
        int		 errors;
        int		 warnings;
        struct process	*stream;
        const char	*phase;
};

/*
 * phase should always point to a literal constant string like "Parsing"
 */
struct reporter *
reporter_new(const char *phase, struct process *stream, int verbose)
{
	struct reporter *r;

	if ((r = malloc(sizeof(struct reporter))) == NULL) {
		return NULL;
	}

	r->verbose = verbose;
        r->errors = 0;
        r->warnings = 0;
        r->finished = 0;
        r->stream = stream;
	if (r->stream == NULL) {
		r->stream = file_open("*stderr", "w");
	}
        r->phase = phase;

	return r;

	if (verbose) {
		process_render(r->stream, "%s started\n", r->phase);
	}
}

void
reporter_free(struct reporter *r)
{
        if (!r->finished) {
                reporter_finish(r);
        }
        stream_close(NULL, r->stream);
	free(r);
}

int
reporter_finish(struct reporter *r)
{
	if (r->verbose) {
		process_render(r->stream,
		    "%s finished with %d errors and %d warnings\n",
		    r->phase, r->errors, r->warnings);
	}
	r->phase = NULL;
        r->finished = 1;
	return r->errors;
}

struct process *
reporter_stream(struct reporter *r)
{
        return r->stream;
}

int
reporter_has_errors(struct reporter *r)
{
	return r->errors > 0;
}

void
report(struct reporter *r, enum report_type rtype, const char *fmt, ...)
{
	va_list args;

	va_start(args, fmt);
        report_va_list(r, rtype, fmt, args);
        va_end(args);
}

void
report_va_list(struct reporter *r, enum report_type rtype, const char *fmt, va_list args)
{
	int i;

        assert(!r->finished);

        process_render(r->stream, "%s %s: ",
            r->phase, rtype == REPORT_ERROR ? "Error" : "Warning");

	for (i = 0; fmt[i] != '\0'; i++) {
		if (fmt[i] == '%') {
			i++;
			switch (fmt[i]) {
			case 's':
				process_render(r->stream, "%s",
				    va_arg(args, char *));
				break;
			case 'd':
				process_render(r->stream, "%d",
				    va_arg(args, int));
				break;
			}
		} else {
			process_render(r->stream, "%c", fmt[i]);
		}
	}

	process_render(r->stream, ".\n");

	switch (rtype) {
	case REPORT_ERROR:
		r->errors++;
		break;
	case REPORT_WARNING:
		r->warnings++;
		break;
	}
}