/*
 * (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
 */

%glr-parser
%locations

%{
#include "dtc.h"
#include "srcpos.h"

int yylex(void);
cell_t cell_from_string(char *s, unsigned int base);

extern struct boot_info *the_boot_info;

%}

%union {
	cell_t cval;
	unsigned int cbase;
	u8 byte;
	char *str;
	struct data data;
	struct property *prop;
	struct property *proplist;
	struct node *node;
	struct node *nodelist;
	int datalen;
	int hexlen;
	u64 addr;
	struct reserve_info *re;
}

%token DT_MEMRESERVE
%token <addr> DT_ADDR
%token <str> DT_PROPNAME
%token <str> DT_NODENAME
%token <cbase> DT_BASE
%token <str> DT_CELL
%token <byte> DT_BYTE
%token <data> DT_STRING
%token <str> DT_UNIT
%token <str> DT_LABEL
%token <str> DT_REF

%type <data> propdata
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
%type <cbase> opt_cell_base
%type <data> celllist
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist

%type <node> devicetree
%type <node> nodedef
%type <node> subnode
%type <nodelist> subnodes
%type <str> label
%type <str> nodename

%%

sourcefile:	memreserves devicetree {
			the_boot_info = build_boot_info($1, $2);
		}
	;

memreserves:	memreserve memreserves {
			$$ = chain_reserve_entry($1, $2);
		}
	|	/* empty */	{
			$$ = NULL;
		}
	;

memreserve:	label DT_MEMRESERVE DT_ADDR DT_ADDR ';' {
			$$ = build_reserve_entry($3, $4, $1);
		}
	|	label DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' {
			$$ = build_reserve_entry($3, $5 - $3 + 1, $1);
		}
	;

devicetree:	'/' nodedef {
			$$ = name_node($2, "", NULL);
		}
	;

nodedef:	'{' proplist subnodes '}' ';' {
			$$ = build_node($2, $3);
		}
	;

proplist:	propdef proplist {
			$$ = chain_property($1, $2);
		}
	|	/* empty */	{
			$$ = NULL;
		}
	;

propdef:	label DT_PROPNAME '=' propdata ';' {
			$$ = build_property($2, $4, $1);
		}
	|	label DT_PROPNAME ';' {
			$$ = build_property($2, empty_data, $1);
		}
	;

propdata:	propdataprefix DT_STRING { $$ = data_merge($1, $2); }
	|	propdataprefix '<' celllist '>' {
			$$ = data_merge(data_append_align($1, sizeof(cell_t)), $3);
		}
	|	propdataprefix '[' bytestring ']' { $$ = data_merge($1, $3); }
	|	propdata DT_LABEL { $$ = data_add_label($1, $2); }
	;

propdataprefix:	propdata ',' { $$ = $1; }
	|	propdataprefix DT_LABEL { $$ = data_add_label($1, $2); }
	|	/* empty */ { $$ = empty_data; }
	;

opt_cell_base:
	  /* empty */
		{ $$ = 16; }
	| DT_BASE
	;

celllist:	celllist opt_cell_base DT_CELL {
			$$ = data_append_cell($1,
					      cell_from_string($3, $2));
		}
	|	celllist DT_REF	{
			$$ = data_append_cell(data_add_fixup($1, $2), -1);
		}
	|	celllist DT_LABEL { $$ = data_add_label($1, $2); }
	|	/* empty */ { $$ = empty_data; }
	;

bytestring:	bytestring DT_BYTE { $$ = data_append_byte($1, $2); }
	|	bytestring DT_LABEL { $$ = data_add_label($1, $2); }
	|	/* empty */ { $$ = empty_data; }
	;

subnodes:	subnode subnodes {
			$$ = chain_node($1, $2);
		}
	|	/* empty */ { $$ = NULL; }
	;

subnode:	label nodename nodedef { $$ = name_node($3, $2, $1); }
	;

nodename:	DT_NODENAME	{ $$ = $1; }
	|	DT_PROPNAME	{ $$ = $1; }
	;

label:		DT_LABEL	{ $$ = $1; }
	|	/* empty */	{ $$ = NULL; }
	;

%%

void yyerror (char const *s)
{
	const char *fname = srcpos_filename_for_num(yylloc.filenum);

	if (strcmp(fname, "-") == 0)
		fname = "stdin";

	fprintf(stderr, "%s:%d %s\n",
		fname, yylloc.first_line, s);
}


/*
 * Convert a string representation of a numeric cell
 * in the given base into a cell.
 *
 * FIXME: should these specification errors be fatal instead?
 */

cell_t cell_from_string(char *s, unsigned int base)
{
	cell_t c;
	char *e;

	c = strtoul(s, &e, base);
	if (*e) {
		fprintf(stderr,
			"Line %d: Invalid cell value '%s' : "
			"%c is not a base %d digit; %d assumed\n",
			yylloc.first_line, s, *e, base, c);
	}

	if (errno == EINVAL || errno == ERANGE) {
		fprintf(stderr,
			"Line %d: Invalid cell value '%s'; %d assumed\n",
			yylloc.first_line, s, c);
		errno = 0;
	}

	return c;
}
