/*
 * This file is part of the bayou project.
 *
 * Copyright (C) 2008 Advanced Micro Devices, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#define _GNU_SOURCE

#include <stdlib.h>
#include <string.h>
#include <expat.h>
#include <ctype.h>
#include "pbuilder.h"

#define STATE_NONE                   0x00
#define STATE_BAYOUCONFIG            0x01
#define STATE_GLOBAL                 0x02
#define STATE_GLOBAL_TIMEOUT         0x03
#define STATE_PAYLOADS               0x04
#define STATE_PAYLOAD                0x05
#define STATE_PAYLOAD_TITLE          0x06
#define STATE_PAYLOAD_FILE           0x07
#define STATE_PAYLOAD_LARNAME        0x08
#define STATE_PAYLOAD_CHAIN          0x09
#define STATE_PAYLOAD_CHAIN_FILE     0x0A
#define STATE_PAYLOAD_CHAIN_LARNAME  0x0B

static struct userdata {
	struct config *config;
	struct pentry *payload;
	struct pentry *chain;
	int state;
} userdata;

static char buffer[8192];

static struct {
	char *element;
	int pstate;
	int state;
} states[] = {
	{"BayouConfig", STATE_NONE, STATE_BAYOUCONFIG},
	{"global", STATE_BAYOUCONFIG, STATE_GLOBAL},
	{"timeout", STATE_GLOBAL, STATE_GLOBAL_TIMEOUT},
	{"payloads", STATE_BAYOUCONFIG, STATE_PAYLOADS},
	{"payload", STATE_PAYLOADS, STATE_PAYLOAD},
	{"title", STATE_PAYLOAD, STATE_PAYLOAD_TITLE},
	{"lar", STATE_PAYLOAD, STATE_PAYLOAD_LARNAME},
	{"file", STATE_PAYLOAD, STATE_PAYLOAD_FILE},
	{"chain", STATE_PAYLOAD, STATE_PAYLOAD_CHAIN},
	{"file", STATE_PAYLOAD_CHAIN, STATE_PAYLOAD_CHAIN_FILE},
	{"lar", STATE_PAYLOAD_CHAIN, STATE_PAYLOAD_CHAIN_LARNAME},
	{NULL},
};

#ifndef __LINUX__
static char *strndup (const char *s, size_t n)
{
	size_t len = strlen (s);
	len = (len<n)?len:n;
	char *cpy = malloc (len + 1);
	if (cpy == NULL)
		return NULL;
	cpy[len] = '\0';
	memcpy (cpy, s, len);
	return cpy;
}
#endif

static struct pentry *newPayload(struct config *config)
{
	struct pentry **tmp, *ret;

	tmp = realloc(config->entries,
		      (config->n_entries + 1) * sizeof(struct pentry *));

	if (tmp == NULL)
		return NULL;

	config->entries = tmp;

	ret = config->entries[config->n_entries] = calloc(sizeof(*ret), 1);

	if (ret == NULL)
		return NULL;

	/* Yes, I want this to be ++config->n_entries (the index is 1 based). */
	ret->index = ++config->n_entries;

	return ret;
}

static void parseFlags(struct pentry *entry, const char *flags)
{
	char *p = (char *)flags;
	char *n;

	while (*p) {
		n = strchr(p, ',');

		if (n)
			*(n++) = 0;

		if (!strcmp(p, "default"))
			entry->flags |= BPT_FLAG_DEFAULT;
		else if (!strcmp(p, "nolist"))
			entry->flags |= BPT_FLAG_NOSHOW;
		else
			warn("W: Unknown payload flag %s\n", p);

		if (!n)
			break;

		for (p = n; *p && isspace(*p); p++) ;
	}
}

static struct pentry *addPayload(struct config *config, const char **attr)
{
	struct pentry *ret = newPayload(config);
	int i = 0;

	if (ret == NULL)
		die("E: Could not allocate memory for a new payload\n");

	while (attr[i] != NULL) {
		if (!strcmp(attr[i], "type")) {
			if (!strcmp(attr[i + 1], "chain"))
				ret->type = BPT_TYPE_CHAIN;
			else if (!strcmp(attr[i + 1], "chooser"))
				ret->type = BPT_TYPE_CHOOSER;
			else
				die("E: Invalid payload type %s\n",
				    attr[i + 1]);
		} else if (!strcmp(attr[i], "flags"))
			parseFlags(ret, attr[i + 1]);

		i += 2;
	}

	return ret;
}

static struct pentry *addChain(struct config *config, struct pentry *parent)
{
	struct pentry *ret = newPayload(config);

	if (ret == NULL)
		die("E: Could not allocate memory for a new payload\n");

	ret->parent = parent->index;
	ret->type = BPT_TYPE_SUBCHAIN;

	return ret;
}

static void start(void *data, const char *el, const char **attr)
{
	int i;
	struct userdata *d = (struct userdata *)data;

	for (i = 0; states[i].element != NULL; i++) {
		if (d->state != states[i].pstate)
			continue;

		if (!strcmp(el, states[i].element)) {
			d->state = states[i].state;
			break;
		}
	}

	if (states[i].element == NULL)
		die("E: Unknown element %s\n", el);

	if (d->state == STATE_PAYLOAD)
		d->payload = addPayload(d->config, attr);

	if (d->state == STATE_PAYLOAD_CHAIN)
		d->chain = addChain(d->config, d->payload);
}

static void data(void *data, const char *val, int len)
{
	struct userdata *d = (struct userdata *)data;
	int l;

	switch (d->state) {
	case STATE_GLOBAL_TIMEOUT:
		d->config->timeout = atoi(val);
		break;
	case STATE_PAYLOAD_TITLE:
		l = sizeof(d->payload->title) - 1 > len ?
		    len : sizeof(d->payload->title) - 1;

		strncpy((char *)d->payload->title, (char *)val, l);
		d->payload->title[l] = '\0';
		break;
	case STATE_PAYLOAD_FILE:
		d->payload->file = strndup(val, len);
		break;
	case STATE_PAYLOAD_LARNAME:
		d->payload->larname = strndup(val, len);
		break;
	case STATE_PAYLOAD_CHAIN_FILE:
		d->chain->file = strndup(val, len);
		break;
	case STATE_PAYLOAD_CHAIN_LARNAME:
		d->chain->larname = strndup(val, len);
		break;
	default:
		break;
	}
}

static void end(void *data, const char *el)
{
	struct userdata *d = (struct userdata *)data;
	int i;

	if (d->state == STATE_PAYLOAD_CHAIN)
		d->chain = NULL;

	if (d->state == STATE_PAYLOAD)
		d->payload = NULL;

	for (i = 0; states[i].element != NULL; i++) {
		if (d->state != states[i].state)
			continue;

		if (!strcmp(el, states[i].element)) {
			d->state = states[i].pstate;
			break;
		}
	}

	if (states[i].element == NULL)
		die("E:  Unable to find the reverse state for %s\n", el);
}

void parseconfig(FILE *stream, struct config *config)
{
	XML_Parser p = XML_ParserCreate(NULL);
	int eof = 0;

	if (p == NULL)
		die("E: Could not create the parser\n");

	XML_SetElementHandler(p, start, end);
	XML_SetCharacterDataHandler(p, data);

	userdata.config = config;

	XML_SetUserData(p, &userdata);

	while (!eof) {
		int len = fread(buffer, 1, 8192, stream);

		eof = feof(stream);

		if (ferror(stream))
			die("E: Error reading the stream\n");

		if (!XML_Parse(p, buffer, len, eof))
			die("E: Error parsing the XML data\n");
	}
}
