#include <stdio.h>
#include <stdlib.h>
#include "email.h"
#include "y.tab.h"

int debug_level = 1;

int
debug(int level, char *fmt, ...) {
	int r;
	va_list ap;
	if (debug_level < level)
		return 0;
	va_start(ap, fmt);
	r = vfprintf(stderr, fmt, ap);
	va_end(ap);
	return r;
}

int
yyerror(char *fmt) {
	fprintf(stderr, "%s\n", fmt);
	return 0;
}

struct header *
new_header(sz *name, sz *value) {
	struct header *h;
	h = malloc(sizeof(struct header));
	if (h) {
		h->name = name;
		h->value = value;
	} else {
		/* avoid memory leaks */
		szfree(name);
		szfree(value);
	}
	return h;
}

struct message *
new_message(struct header *h) {
	struct message *m;
	m = malloc(sizeof(struct message));
	if (m) {
		m->num_headers = m->max_headers = 0;
		m->headers = 0;
		m->body = 0;
		m->fromline = 0;
		if (h) {
			add_header(m, h);
		}
	} else {
		free_header(h);
	}
	return m;
}

void
free_message(struct message *m) {
	int i;
	if (!m)
		return;
	if (m->headers) {
		for (i = 0; i < m->num_headers; ++i) {
			free_header(m->headers[i]);
		}
	}
	szfree(m->fromline);
	szfree(m->body);
	free(m);
}

void
free_header(struct header *h) {
	if (!h)
		return;
	szfree(h->name);
	szfree(h->value);
	free(h);
}

void
add_header(struct message *m, struct header *h) {
	if (m->num_headers + 1 > m->max_headers) {
		int n = m->max_headers + 5;
		int i;
		struct header **new = malloc(sizeof(struct header *) * n);

		if (!new) {
			char *s = 0;
			if (h && h->name)
				s = szdata(h->name);
			fprintf(stderr, "couldn't add header '%s', no memory\n",
				s ? s : "<null>");
			return;
		}
		for (i = 0; i < m->num_headers; ++i) {
			new[i] = m->headers[i];
		}
		free(m->headers);
		m->headers = new;
		m->max_headers = n;
	}
	m->headers[m->num_headers++] = h;
}

struct mlist *
new_mlist(struct message *m) {
	struct mlist *ml = malloc(sizeof(struct mlist));
	if (ml) {
		ml->next = 0;
		ml->m = m;
	}
	return ml;
}

sz *
get_header(struct message *m, char *s) {
	int i;
	if (!m || !m->headers)
		return 0;
	for (i = 0; i < m->num_headers; ++i) {
		if (!szcmp(m->headers[i]->name, s)) {
			return m->headers[i]->value;
		}
	}
	return 0;
}
