/*
 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
 *
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 *  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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 *                                                                   USA
 */

#include "dtc.h"
#include "srcpos.h"

extern FILE *yyin;
extern int yyparse(void);
extern YYLTYPE yylloc;

struct boot_info *the_boot_info;
bool treesource_error;

struct boot_info *dt_from_source(const char *fname)
{
	the_boot_info = NULL;
	treesource_error = false;

	srcfile_push(fname);
	yyin = current_srcfile->f;
	yylloc.file = current_srcfile;

	if (yyparse() != 0)
		die("Unable to parse input tree\n");

	if (treesource_error)
		die("Syntax error parsing input tree\n");

	return the_boot_info;
}

static void write_prefix(FILE *f, int level)
{
	int i;

	for (i = 0; i < level; i++)
		fputc('\t', f);
}

static bool isstring(char c)
{
	return (isprint((unsigned char)c)
		|| (c == '\0')
		|| strchr("\a\b\t\n\v\f\r", c));
}

static void write_propval_string(FILE *f, struct data val)
{
	const char *str = val.val;
	int i;
	struct marker *m = val.markers;

	assert(str[val.len-1] == '\0');

	while (m && (m->offset == 0)) {
		if (m->type == LABEL)
			fprintf(f, "%s: ", m->ref);
		m = m->next;
	}
	fprintf(f, "\"");

	for (i = 0; i < (val.len-1); i++) {
		char c = str[i];

		switch (c) {
		case '\a':
			fprintf(f, "\\a");
			break;
		case '\b':
			fprintf(f, "\\b");
			break;
		case '\t':
			fprintf(f, "\\t");
			break;
		case '\n':
			fprintf(f, "\\n");
			break;
		case '\v':
			fprintf(f, "\\v");
			break;
		case '\f':
			fprintf(f, "\\f");
			break;
		case '\r':
			fprintf(f, "\\r");
			break;
		case '\\':
			fprintf(f, "\\\\");
			break;
		case '\"':
			fprintf(f, "\\\"");
			break;
		case '\0':
			fprintf(f, "\", ");
			while (m && (m->offset <= (i + 1))) {
				if (m->type == LABEL) {
					assert(m->offset == (i+1));
					fprintf(f, "%s: ", m->ref);
				}
				m = m->next;
			}
			fprintf(f, "\"");
			break;
		default:
			if (isprint((unsigned char)c))
				fprintf(f, "%c", c);
			else
				fprintf(f, "\\x%02hhx", c);
		}
	}
	fprintf(f, "\"");

	/* Wrap up any labels at the end of the value */
	for_each_marker_of_type(m, LABEL) {
		assert (m->offset == val.len);
		fprintf(f, " %s:", m->ref);
	}
}

static void write_propval_cells(FILE *f, struct data val)
{
	void *propend = val.val + val.len;
	cell_t *cp = (cell_t *)val.val;
	struct marker *m = val.markers;

	fprintf(f, "<");
	for (;;) {
		while (m && (m->offset <= ((char *)cp - val.val))) {
			if (m->type == LABEL) {
				assert(m->offset == ((char *)cp - val.val));
				fprintf(f, "%s: ", m->ref);
			}
			m = m->next;
		}

		fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
		if ((void *)cp >= propend)
			break;
		fprintf(f, " ");
	}

	/* Wrap up any labels at the end of the value */
	for_each_marker_of_type(m, LABEL) {
		assert (m->offset == val.len);
		fprintf(f, " %s:", m->ref);
	}
	fprintf(f, ">");
}

static void write_propval_bytes(FILE *f, struct data val)
{
	void *propend = val.val + val.len;
	const char *bp = val.val;
	struct marker *m = val.markers;

	fprintf(f, "[");
	for (;;) {
		while (m && (m->offset == (bp-val.val))) {
			if (m->type == LABEL)
				fprintf(f, "%s: ", m->ref);
			m = m->next;
		}

		fprintf(f, "%02hhx", (unsigned char)(*bp++));
		if ((const void *)bp >= propend)
			break;
		fprintf(f, " ");
	}

	/* Wrap up any labels at the end of the value */
	for_each_marker_of_type(m, LABEL) {
		assert (m->offset == val.len);
		fprintf(f, " %s:", m->ref);
	}
	fprintf(f, "]");
}

static void write_propval(FILE *f, struct property *prop)
{
	int len = prop->val.len;
	const char *p = prop->val.val;
	struct marker *m = prop->val.markers;
	int nnotstring = 0, nnul = 0;
	int nnotstringlbl = 0, nnotcelllbl = 0;
	int i;

	if (len == 0) {
		fprintf(f, ";\n");
		return;
	}

	for (i = 0; i < len; i++) {
		if (! isstring(p[i]))
			nnotstring++;
		if (p[i] == '\0')
			nnul++;
	}

	for_each_marker_of_type(m, LABEL) {
		if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
			nnotstringlbl++;
		if ((m->offset % sizeof(cell_t)) != 0)
			nnotcelllbl++;
	}

	fprintf(f, " = ");
	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
	    && (nnotstringlbl == 0)) {
		write_propval_string(f, prop->val);
	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
		write_propval_cells(f, prop->val);
	} else {
		write_propval_bytes(f, prop->val);
	}

	fprintf(f, ";\n");
}

static void write_tree_source_node(FILE *f, struct node *tree, int level)
{
	struct property *prop;
	struct node *child;
	struct label *l;

	write_prefix(f, level);
	for_each_label(tree->labels, l)
		fprintf(f, "%s: ", l->label);
	if (tree->name && (*tree->name))
		fprintf(f, "%s {\n", tree->name);
	else
		fprintf(f, "/ {\n");

	for_each_property(tree, prop) {
		write_prefix(f, level+1);
		for_each_label(prop->labels, l)
			fprintf(f, "%s: ", l->label);
		fprintf(f, "%s", prop->name);
		write_propval(f, prop);
	}
	for_each_child(tree, child) {
		fprintf(f, "\n");
		write_tree_source_node(f, child, level+1);
	}
	write_prefix(f, level);
	fprintf(f, "};\n");
}


void dt_to_source(FILE *f, struct boot_info *bi)
{
	struct reserve_info *re;

	fprintf(f, "/dts-v1/;\n\n");

	for (re = bi->reservelist; re; re = re->next) {
		struct label *l;

		for_each_label(re->labels, l)
			fprintf(f, "%s: ", l->label);
		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
			(unsigned long long)re->re.address,
			(unsigned long long)re->re.size);
	}

	write_tree_source_node(f, bi->dt, 0);
}

