/*-
 * Copyright (c)1997-2005 by Hartmut Brandt
 * 	All rights reserved.
 *
 * Author: Harti Brandt <harti@freebsd.org>
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Begemot: libbegemot/verb.c,v 1.8 2005/06/01 07:51:14 brandt_h Exp $
 */
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "begemot.h"
# include "private.h"

static verb_option_t verb_dflt[] = {
	{ "verbose", 0 },
	{ NULL, 0 }
};
static verb_option_t *verb_options = verb_dflt;

/*
 * Parse a verbose option
 */
void
verb_option(char *opt)
{
	char *end, *p, *eq;
	u_int val;
	int i, inc;

	while(*opt != '\0') {
		if(*opt == ',') {
			opt++;
			continue;
		}
		inc = 0;

		if((p = strchr(opt, ',')) == NULL)
			p = opt + strlen(opt);

		if((eq = strnchr(opt, '=', p - opt)) != NULL) {
			val = (u_int)strtoul(eq+1, &end, 0);
			if(*end != '\0' && *end != ',') {
				warn("%.*s: bad debug value", p - opt, opt);
				val = 0;
			}
		} else {
			eq = p;
			inc = 1;
			val = 1;
		}
		if((size_t)(eq - opt) == strlen("all")
		  && strncasecmp(opt, "all", eq - opt) == 0) {
			for(i = 0; verb_options[i].opt; i++)
				if(inc)
					verb_options[i].level += val;
				else
					verb_options[i].level = val;

		} else {
			for(i = 0; verb_options[i].opt; i++)
				if((size_t)(eq-opt)==strlen(verb_options[i].opt)
				  && strncasecmp(verb_options[i].opt,opt,eq-opt) == 0) {
					if(inc)
						verb_options[i].level += val;
					else
						verb_options[i].level = val;
					break;
				}
			if(verb_options[i].opt == NULL)
				warn("%.*s: bad verbose option", eq - opt, opt);
		}
		opt = p;
	}
}

/*
 * Update verbose options from a file
 */
void
verb_update(FILE *fp)
{
	char *line;

	while((line = readline(fp)) != NULL) {
		verb_option(line);
		free(line);
	}
}

void
verb(u_int opt, u_int level, const char *fmt, ...)
{
	va_list ap;

	if(verb_options[opt].level < level)
		return;
	va_start(ap, fmt);
	begemot_common_err(verb_options[opt].opt, "\n", fmt, ap);
	va_end(ap);
}
void
vverb(u_int opt, u_int level, const char *fmt, va_list ap)
{
	if(verb_options[opt].level < level)
		return;

	begemot_common_err(verb_options[opt].opt, "\n", fmt, ap);
}

void
verbn(u_int opt, u_int level, const char *fmt, ...)
{
	va_list ap;

	if(verb_options[opt].level < level)
		return;
	va_start(ap, fmt);
	begemot_common_err(verb_options[opt].opt, NULL, fmt, ap);
	va_end(ap);
}
void
vverbn(u_int opt, u_int level, const char *fmt, va_list ap)
{
	if(verb_options[opt].level < level)
		return;

	begemot_common_err(verb_options[opt].opt, NULL, fmt, ap);
}

void
verbc(u_int opt, u_int level, const char *fmt, ...)
{
	va_list ap;

	if(verb_options[opt].level < level)
		return;
	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
}
void
vverbc(u_int opt, u_int level, const char *fmt, va_list ap)
{
	if(verb_options[opt].level < level)
		return;

	vfprintf(stderr, fmt, ap);
}

u_int
verb_level(u_int opt)
{
	return verb_options[opt].level;
}

void
verb_opts(verb_option_t *v)
{
	verb_options = v;
}

# ifdef TEST

# include <unistd.h>

verb_option_t verbs[] = {
	{ "dump",	0 },
	{ "foo",	0 },
	{ "bar",	0 },
	{ NULL, 0 },
};

void
dump_verb()
{
	u_int i;

	for(i = 0; verbs[i].opt; i++)
		printf("%s=%u\n", verbs[i].opt, verbs[i].level);
}

int
main(int argc, char *argv[])
{
	int opt;

	verb_opts(verbs);
	while((opt = getopt(argc, argv, "v:")) != EOF)
		switch(opt) {
		  case 'v':
			verb_option(optarg);
			dump_verb();
			break;
		}

	verb_option("all");
	dump_verb();
	verb_option("all=2");
	dump_verb();
	verb_option("all=1,dump=5");
	dump_verb();

	return 0;
}

# endif


syntax highlighted by Code2HTML, v. 0.9.1