/*
 * Sparse c2xml
 *
 * Dumps the parse tree as an xml document
 *
 * Copyright (C) 2007 Rob Taylor
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <libxml/parser.h>
#include <libxml/tree.h>

#include "expression.h"
#include "parse.h"
#include "scope.h"
#include "symbol.h"

static xmlDocPtr doc = NULL;       /* document pointer */
static xmlNodePtr root_node = NULL;/* root node pointer */
static int idcount = 0;

static void examine_symbol(struct symbol *sym, xmlNodePtr node);

static xmlAttrPtr newProp(xmlNodePtr node, const char *name, const char *value)
{
	return xmlNewProp(node, BAD_CAST name, BAD_CAST value);
}

static xmlAttrPtr newNumProp(xmlNodePtr node, const char *name, int value)
{
	char buf[256];
	snprintf(buf, 256, "%d", value);
	return newProp(node, name, buf);
}

static xmlAttrPtr newIdProp(xmlNodePtr node, const char *name, unsigned int id)
{
	char buf[256];
	snprintf(buf, 256, "_%d", id);
	return newProp(node, name, buf);
}

static xmlNodePtr new_sym_node(struct symbol *sym, const char *name, xmlNodePtr parent)
{
	xmlNodePtr node;
	const char *ident = show_ident(sym->ident);

	assert(name != NULL);
	assert(sym != NULL);
	assert(parent != NULL);

	node = xmlNewChild(parent, NULL, BAD_CAST "symbol", NULL);

	newProp(node, "type", name);

	newIdProp(node, "id", idcount);

	if (sym->ident && ident)
		newProp(node, "ident", ident);
	newProp(node, "file", stream_name(sym->pos.stream));

	newNumProp(node, "start-line", sym->pos.line);
	newNumProp(node, "start-col", sym->pos.pos);

	if (sym->endpos.type) {
		newNumProp(node, "end-line", sym->endpos.line);
		newNumProp(node, "end-col", sym->endpos.pos);
		if (sym->pos.stream != sym->endpos.stream)
			newProp(node, "end-file", stream_name(sym->endpos.stream));
        }
	sym->aux = node;

	idcount++;

	return node;
}

static inline void examine_members(struct symbol_list *list, xmlNodePtr node)
{
	struct symbol *sym;

	FOR_EACH_PTR(list, sym) {
		examine_symbol(sym, node);
	} END_FOR_EACH_PTR(sym);
}

static void examine_modifiers(struct symbol *sym, xmlNodePtr node)
{
	const char *modifiers[] = {
			"auto",
			"register",
			"static",
			"extern",
			"const",
			"volatile",
			"signed",
			"unsigned",
			"char",
			"short",
			"long",
			"long-long",
			"typedef",
			NULL,
			NULL,
			NULL,
			NULL,
			NULL,
			"inline",
			"addressable",
			"nocast",
			"noderef",
			"accessed",
			"toplevel",
			"label",
			"assigned",
			"type-type",
			"safe",
			"user-type",
			"force",
			"explicitly-signed",
			"bitwise"};

	int i;

	if (sym->namespace != NS_SYMBOL)
		return;

	/*iterate over the 32 bit bitfield*/
	for (i=0; i < 32; i++) {
		if ((sym->ctype.modifiers & 1<<i) && modifiers[i])
			newProp(node, modifiers[i], "1");
	}
}

static void
examine_layout(struct symbol *sym, xmlNodePtr node)
{
	examine_symbol_type(sym);

	newNumProp(node, "bit-size", sym->bit_size);
	newNumProp(node, "alignment", sym->ctype.alignment);
	newNumProp(node, "offset", sym->offset);
	if (is_bitfield_type(sym)) {
		newNumProp(node, "bit-offset", sym->bit_offset);
	}
}

static void examine_symbol(struct symbol *sym, xmlNodePtr node)
{
	xmlNodePtr child = NULL;
	const char *base;
	int array_size;

	if (!sym)
		return;
	if (sym->aux)		/*already visited */
		return;

	if (sym->ident && sym->ident->reserved)
		return;

	child = new_sym_node(sym, get_type_name(sym->type), node);
	examine_modifiers(sym, child);
	examine_layout(sym, child);

	if (sym->ctype.base_type) {
		if ((base = builtin_typename(sym->ctype.base_type)) == NULL) {
			if (!sym->ctype.base_type->aux) {
				examine_symbol(sym->ctype.base_type, root_node);
			}
			xmlNewProp(child, BAD_CAST "base-type",
			           xmlGetProp((xmlNodePtr)sym->ctype.base_type->aux, BAD_CAST "id"));
		} else {
			newProp(child, "base-type-builtin", base);
		}
	}
	if (sym->array_size) {
		/* TODO: modify get_expression_value to give error return */
		array_size = get_expression_value(sym->array_size);
		newNumProp(child, "array-size", array_size);
	}


	switch (sym->type) {
	case SYM_STRUCT:
	case SYM_UNION:
		examine_members(sym->symbol_list, child);
		break;
	case SYM_FN:
		examine_members(sym->arguments, child);
		break;
	case SYM_UNINITIALIZED:
		newProp(child, "base-type-builtin", builtin_typename(sym));
		break;
	default:
		break;
	}
	return;
}

static struct position *get_expansion_end (struct token *token)
{
	struct token *p1, *p2;

	for (p1=NULL, p2=NULL;
	     !eof_token(token);
	     p2 = p1, p1 = token, token = token->next);

	if (p2)
		return &(p2->pos);
	else
		return NULL;
}

static void examine_macro(struct symbol *sym, xmlNodePtr node)
{
	struct position *pos;

	/* this should probably go in the main codebase*/
	pos = get_expansion_end(sym->expansion);
	if (pos)
		sym->endpos = *pos;
	else
		sym->endpos = sym->pos;

	new_sym_node(sym, "macro", node);
}

static void examine_namespace(struct symbol *sym)
{
	if (sym->ident && sym->ident->reserved)
		return;

	switch(sym->namespace) {
	case NS_MACRO:
		examine_macro(sym, root_node);
		break;
	case NS_TYPEDEF:
	case NS_STRUCT:
	case NS_SYMBOL:
		examine_symbol(sym, root_node);
		break;
	case NS_NONE:
	case NS_LABEL:
	case NS_ITERATOR:
	case NS_UNDEF:
	case NS_PREPROCESSOR:
	case NS_KEYWORD:
		break;
	default:
		die("Unrecognised namespace type %d",sym->namespace);
	}

}

static int get_stream_id (const char *name)
{
	int i;
	for (i=0; i<input_stream_nr; i++) {
		if (strcmp(name, stream_name(i))==0)
			return i;
	}
	return -1;
}

static inline void examine_symbol_list(const char *file, struct symbol_list *list)
{
	struct symbol *sym;
	int stream_id = get_stream_id (file);

	if (!list)
		return;
	FOR_EACH_PTR(list, sym) {
		if (sym->pos.stream == stream_id)
			examine_namespace(sym);
	} END_FOR_EACH_PTR(sym);
}

int main(int argc, char **argv)
{
	struct string_list *filelist = NULL;
	struct symbol_list *symlist = NULL;
	char *file;

	doc = xmlNewDoc(BAD_CAST "1.0");
	root_node = xmlNewNode(NULL, BAD_CAST "parse");
	xmlDocSetRootElement(doc, root_node);

/* - A DTD is probably unnecessary for something like this

	dtd = xmlCreateIntSubset(doc, "parse", "http://www.kernel.org/pub/software/devel/sparse/parse.dtd" NULL, "parse.dtd");

	ns = xmlNewNs (root_node, "http://www.kernel.org/pub/software/devel/sparse/parse.dtd", NULL);

	xmlSetNs(root_node, ns);
*/
	symlist = sparse_initialize(argc, argv, &filelist);

	FOR_EACH_PTR(filelist, file) {
		examine_symbol_list(file, symlist);
		sparse_keep_tokens(file);
		examine_symbol_list(file, file_scope->symbols);
		examine_symbol_list(file, global_scope->symbols);
	} END_FOR_EACH_PTR(file);


	xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);
	xmlFreeDoc(doc);
	xmlCleanupParser();

	return 0;
}
