/*
* (c) 2020 Vincenzo "KatolaZ" Nicosia <katolaz@freaknet.org>
* 
* A simple xml-to-rsv converter, based on xmlparser by Hiltjo Posthuma
* http://codemadness.org/git/xmlparser/
*
* You can use, distribute, modify, and/or redistribute this program under
* the terms of the ISC LICENSE. See LICENSE for details.
*
*/


#include <sys/types.h>

#include <stdio.h>
#include <string.h>

#include "xml.h"

#define STR_MAX 128
#define DEPTH_MAX 50


/* tag stack */

typedef struct {
	int top;
	char st[DEPTH_MAX][STR_MAX];
} tstack_t;

int stack_push(tstack_t *t, const char *c){
	if (t->top < DEPTH_MAX){
		t->top ++;
		strncpy(t->st[t->top], c, STR_MAX);
		return 0;
	}
	return -1;
}	

char* stack_pop(tstack_t *t){
	if (t->top >= 0)
		return t->st[t->top--];
	return NULL;
} 

char* stack_peek(tstack_t *t){
	if (t->top >= 0)
		return t->st[t->top];
	return NULL;
}

int stack_empty(tstack_t *t){
	return (t->top < 0);
}

void stack_init(tstack_t *t){
	t->top = -1;
}


/* utility functions */

void print_no_cr(FILE *f, const char *c){
	char *tmp = c;
	while (c != NULL){
		tmp = strchr(c, '\n');
		if (tmp != NULL)
			*tmp = '\0';
		fprintf(f, "%s", c);
		if (tmp != NULL)
			c = tmp + 1;
		else
			c = NULL;
	}
}

void print_cur_str(FILE *f, tstack_t *t){
	int i;
	for (i=0; i<=t->top; i++){
		fprintf(f, "/%s", t->st[i]);
	}
}

/* global variables */

tstack_t st;


/* xml callbacks */

void
xmlattr(XMLParser *x, const char *t, size_t tl, const char *a, size_t al,
        const char *v, size_t vl)
{
	printf("\t%s=%s", a, v);
}

void
xmlattrentity(XMLParser *x, const char *t, size_t tl, const char *a, size_t al,
              const char *v, size_t vl)
{
	printf("attrentity: %s\n", a);
}

void
xmlattrend(XMLParser *x, const char *t, size_t tl, const char *a, size_t al)
{
}

void
xmlattrstart(XMLParser *x, const char *t, size_t tl, const char *a, size_t al)
{
}

void
xmlcdatastart(XMLParser *x)
{
}

void
xmlcdata(XMLParser *x, const char *d, size_t dl)
{
	printf("\t%s", d);
}

void
xmlcdataend(XMLParser *x)
{
}

void
xmlcommentstart(XMLParser *x)
{
}

void
xmlcomment(XMLParser *x, const char *c, size_t cl)
{
}

void
xmlcommentend(XMLParser *x)
{
}

void
xmldata(XMLParser *x, const char *d, size_t dl)
{
	printf("\t");
	print_no_cr(stdout, d);
}

void
xmldataend(XMLParser *x)
{
}

void
xmldataentity(XMLParser *x, const char *d, size_t dl)
{
}

void
xmldatastart(XMLParser *x)
{
}

void
xmltagend(XMLParser *x, const char *t, size_t tl, int isshort)
{
	char *tag;
	if (stack_empty(&st)){
		fprintf(stderr, "Error: tag-end '%s' before any open tag", t);
	}
	tag = stack_pop(&st);
	if (strcmp(t, tag)){
		fprintf(stderr, "Error: tag-end '%s' closes tag '%s'", t, tag);
	}
	/* printf("\n"); */
}

void
xmltagstart(XMLParser *x, const char *t, size_t tl)
{
	if (stack_push(&st, t)){
		fprintf(stderr, "Error: stack full. Ignoring tag '%s' (parent tag: '%s')\n", t, stack_peek(&st));
		return;
	}
	printf("\n");
	print_cur_str(stdout, &st);
}

void
xmltagstartparsed(XMLParser *x, const char *t, size_t tl, int isshort)
{
	/* printf("inside tagstartparsed\n"); */
}

int
main(void)
{
	stack_init(&st);
	XMLParser x = { 0 };

	x.xmlattr = xmlattr;
	x.xmlattrend = xmlattrend;
	x.xmlattrstart = xmlattrstart;
	x.xmlattrentity = xmlattrentity;
	x.xmlcdatastart = xmlcdatastart;
	x.xmlcdata = xmlcdata;
	x.xmlcdataend = xmlcdataend;
	x.xmlcommentstart = xmlcommentstart;
	x.xmlcomment = xmlcomment;
	x.xmlcommentend = xmlcommentend;
	x.xmldata = xmldata;
	x.xmldataend = xmldataend;
	x.xmldataentity = xmldataentity;
	x.xmldatastart = xmldatastart;
	x.xmltagend = xmltagend;
	x.xmltagstart = xmltagstart;
	x.xmltagstartparsed = xmltagstartparsed;

	x.getnext = getchar;

	xml_parse(&x);
	printf("\n");
	return 0;
}