Patchwork Refactor sconfig

login
register
about
Submitter Patrick Georgi
Date 2010-05-05 11:14:17
Message ID <4BE15309.4020309@georgi-clan.de>
Download mbox | patch
Permalink /patch/1287/
State Accepted
Headers show

Comments

Patrick Georgi - 2010-05-05 11:14:17
Hi,

attached patch moves all the device tree processing out of the parser
into a dedicated C source file.
It should help understanding what the parser is doing and thus help with
further sconfig development.

Unfortunately the patch isn't very readable, due to autogenerated code
(in the _shipped files), and because I svn-copied sconfig.y to the new
files:
- sconfig.h (shared data structures)
- main.c (device tree handling, main())

The change also requires some modifications to the build. The more
general issue of cleaning up this area of the build system is registered
as ticket #160 (assigned to me).

I tested the patch by doing two full abuild runs (slightly modified to
only emit static.c), with and without the patch.
All mainboards' static.c were identical with or without the patch.


Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Peter Stuge - 2010-05-05 11:17:58
Patrick Georgi wrote:
> Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>

Acked-by: Peter Stuge <peter@stuge.se>

Patch

Index: Makefile
===================================================================
--- Makefile	(revision 5522)
+++ Makefile	(working copy)
@@ -170,7 +170,7 @@ 
 
 $(objutil)/%.o: $(objutil)/%.c
 	@printf "    HOSTCC     $(subst $(objutil)/,,$(@))\n"
-	$(HOSTCC) -MMD $(HOSTCFLAGS) -c -o $@ $<
+	$(HOSTCC) -MMD -I$(subst $(objutil)/,util/,$(dir $<)) -I$(dir $<) $(HOSTCFLAGS) -c -o $@ $<
 
 $(obj)/%.o: $(obj)/%.c $(obj)/config.h
 	@printf "    CC         $(subst $(obj)/,,$(@))\n"
Index: util/sconfig/sconfig.tab.h_shipped
===================================================================
--- util/sconfig/sconfig.tab.h_shipped	(revision 5522)
+++ util/sconfig/sconfig.tab.h_shipped	(working copy)
@@ -2,20 +2,20 @@ 
 /* A Bison parser, made by GNU Bison 2.4.1.  */
 
 /* Skeleton interface for Bison's Yacc-like parsers in C
-
+   
       Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
-
+   
    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 3 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, see <http://www.gnu.org/licenses/>.  */
 
@@ -28,7 +28,7 @@ 
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
Index: util/sconfig/sconfig.y
===================================================================
--- util/sconfig/sconfig.y	(revision 5522)
+++ util/sconfig/sconfig.y	(working copy)
@@ -19,108 +19,10 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
+#include "sconfig.h"
 
-enum devtype { chip, device };
+struct device *cur_parent, *cur_bus;
 
-struct resource;
-struct resource {
-	int type;
-	int index;
-	int base;
-	struct resource *next;
-};
-
-struct reg;
-struct reg {
-	char *key;
-	char *value;
-	struct reg *next;
-};
-
-struct device;
-struct device {
-	int id;
-	int enabled;
-	int used;
-	int multidev;
-	int link;
-	int rescnt;
-	int chiph_exists;
-	char *ops;
-	char *name;
-	char *aliased_name;
-	char *name_underscore;
-	char *path;
-	int path_a;
-	int path_b;
-	int bustype;
-	enum devtype type;
-	struct device *parent;
-	struct device *bus;
-	struct device *next;
-	struct device *nextdev;
-	struct device *children;
-	struct device *latestchild;
-	struct device *next_sibling;
-	struct device *sibling;
-	struct device *chip;
-	struct resource *res;
-	struct reg *reg;
-} *head, *lastdev, *cur_parent, *cur_bus, root;
-
-struct header;
-struct header {
-	char *name;
-	struct header *next;
-} headers;
-
-int devcount = 0;
-
-struct device *new_dev() {
-	struct device *dev = malloc(sizeof(struct device));
-	memset(dev, 0, sizeof(struct device));
-	dev->id = ++devcount;
-	dev->parent = cur_parent;
-	dev->bus = cur_bus;
-	head->next = dev;
-	head = dev;
-	return dev;
-}
-
-int device_match(struct device *a, struct device *b) {
-	if ((a->bustype == b->bustype) && (a->bus == b->bus) && (a->path_a == b->path_a) && (a->path_b == b->path_b))
-		return 1;
-	return 0;
-}
-
-void fold_in(struct device *parent) {
-	struct device *child = parent->children;
-	struct device *latest = 0;
-	while (child != latest) {
-		if (child->children) {
-			if (!latest) latest = child->children;
-			parent->latestchild->next_sibling = child->children;
-			parent->latestchild = child->latestchild;
-		}
-		child = child->next_sibling;
-	}
-}
-
-int yywrap(void) {
-	return 1;
-}
-
-void yyerror (char const *str)
-{
-	fprintf (stderr, "%s\n", str);
-}
 %}
 %union {
 	struct device *device;
@@ -129,26 +31,8 @@ 
 }
 %token CHIP DEVICE REGISTER BOOL BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC APIC_CLUSTER PCI_DOMAIN IRQ DRQ IO NUMBER
 %%
-devtree: devchip {
-	root.next_sibling = root.children;
-	root.next_sibling->next_sibling = root.next_sibling->children;
+devtree: devchip { postprocess_devtree(); } ;
 
-	struct device *dev = &root;
-	while (dev) {
-		/* skip "chip" elements in children chain */
-		while (dev->children && (dev->children->type == chip)) dev->children = dev->children->children;
-		/* skip "chip" elements and functions of the same device in sibling chain */
-		while (dev->sibling && dev->sibling->used) dev->sibling = dev->sibling->sibling;
-		/* If end of chain, and parent is a chip, move on */
-		if (!dev->sibling && (dev->parent->type == chip)) dev->sibling = dev->parent->sibling;
-		/* skip chips */
-		while (dev->sibling && dev->sibling->type == chip) dev->sibling = dev->sibling->children;
-		/* skip duplicate function elements in nextdev chain */
-		while (dev->nextdev && dev->nextdev->used) dev->nextdev = dev->nextdev->nextdev;
-		dev = dev->next_sibling;
-	}
-	};
-
 devchip: chip | device ;
 
 devices: devices devchip | devices registers | ;
@@ -156,346 +40,31 @@ 
 devicesorresources: devicesorresources devchip | devicesorresources resource | ;
 
 chip: CHIP STRING /* == path */ {
-	$<device>$ = new_dev();
-	$<device>$->chiph_exists = 1;
-	$<device>$->name = $<string>2;
-	$<device>$->name_underscore = strdup($<device>$->name);
-	char *c;
-	for (c = $<device>$->name_underscore; *c; c++) {
-		if (*c == '/') *c = '_';
-		if (*c == '-') *c = '_';
-	}
-	$<device>$->type = chip;
-	$<device>$->chip = $<device>$;
-
-	struct stat st;
-	char *chip_h = malloc(strlen($<string>2)+12);
-	sprintf(chip_h, "src/%s/chip.h", $<string>2);
-	if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
-		$<device>$->chiph_exists = 0;
-
-	if (cur_parent->latestchild) {
-		cur_parent->latestchild->next_sibling = $<device>$;
-		cur_parent->latestchild->sibling = $<device>$;
-	}
-	cur_parent->latestchild = $<device>$;
-	if (!cur_parent->children)
-		cur_parent->children = $<device>$;
-
+	$<device>$ = new_chip($<string>2);
 	cur_parent = $<device>$;
 }
 	devices END {
 	cur_parent = $<device>3->parent;
-
 	fold_in($<device>3);
-
-	if ($<device>3->chiph_exists) {
-		int include_exists = 0;
-		struct header *h = &headers;
-		while (h->next) {
-			int result = strcmp($<device>3->name, h->next->name);
-			if (result == 0) {
-				include_exists = 1;
-				break;
-			}
-			if (result < 0) break;
-			h = h->next;
-		}
-		if (!include_exists) {
-			struct header *tmp = h->next;
-			h->next = malloc(sizeof(struct header));
-			memset(h->next, 0, sizeof(struct header));
-			h->next->name = $<device>3->name;
-			h->next->next = tmp;
-			break;
-		}
-	}
+	add_header($<device>3);
 };
 
 device: DEVICE BUS NUMBER /* == devnum */ BOOL {
-	$<device>$ = new_dev();
-	$<device>$->bustype = $<number>2;
-
-	char *tmp;
-	$<device>$->path_a = strtol(strdup($<string>3), &tmp, 16);
-	if (*tmp == '.') {
-		tmp++;
-		$<device>$->path_b = strtol(tmp, NULL, 16);
-	}
-
-	char *name = malloc(10);
-	sprintf(name, "_dev%d", $<device>$->id);
-	$<device>$->name = name;
-	$<device>$->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr
-	$<device>$->type = device;
-	$<device>$->enabled = $<number>4;
-	$<device>$->chip = $<device>$->parent->chip;
-
-	if (cur_parent->latestchild) {
-		cur_parent->latestchild->next_sibling = $<device>$;
-		cur_parent->latestchild->sibling = $<device>$;
-	}
-	cur_parent->latestchild = $<device>$;
-	if (!cur_parent->children)
-		cur_parent->children = $<device>$;
-
-	lastdev->nextdev = $<device>$;
-	lastdev = $<device>$;
-	if ($<number>2 == PCI) {
-		$<device>$->path = ".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}";
-	}
-	if ($<number>2 == PNP) {
-		$<device>$->path = ".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}";
-	}
-	if ($<number>2 == I2C) {
-		$<device>$->path = ".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}";
-	}
-	if ($<number>2 == APIC) {
-		$<device>$->path = ".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}";
-	}
-	if ($<number>2 == APIC_CLUSTER) {
-		$<device>$->path = ".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}";
-	}
-	if ($<number>2 == PCI_DOMAIN) {
-		$<device>$->path = ".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}";
-	}
+	$<device>$ = new_device($<number>2, $<string>3, $<number>4);
 	cur_parent = $<device>$;
 	cur_bus = $<device>$;
 }
 	devicesorresources END {
 	cur_parent = $<device>5->parent;
 	cur_bus = $<device>5->bus;
-
 	fold_in($<device>5);
-
-	struct device *d = $<device>5->children;
-	while (d) {
-		int link = 0;
-		struct device *cmp = d->next_sibling;
-		while (cmp && (cmp->bus == d->bus) && (cmp->path_a == d->path_a) && (cmp->path_b == d->path_b)) {
-			if (cmp->type==device && !cmp->used) {
-				if (device_match(d, cmp)) {
-					d->multidev = 1;
-
-					cmp->aliased_name = malloc(12);
-					sprintf(cmp->aliased_name, "_dev%d", cmp->id);
-					cmp->id = d->id;
-					cmp->name = d->name;
-					cmp->used = 1;
-					cmp->link = ++link;
-				}
-			}
-			cmp = cmp->next_sibling;
-		}
-		d = d->next_sibling;
-	}
+	alias_siblings($<device>5->children);
 };
 
 resource: RESOURCE NUMBER /* == resnum */ EQUALS NUMBER /* == resval */
-	{
-		struct resource *r = malloc(sizeof(struct resource));
-		memset (r, 0, sizeof(struct resource));
-		r->type = $<number>1;
-		r->index = strtol($<string>2, NULL, 0);
-		r->base = strtol($<string>4, NULL, 0);
-		if (cur_parent->res) {
-			struct resource *head = cur_parent->res;
-			while (head->next) head = head->next;
-			head->next = r;
-		} else {
-			cur_parent->res = r;
-		}
-		cur_parent->rescnt++;
-	}
-	;
+	{ add_resource($<number>1, strtol($<string>2, NULL, 0), strtol($<string>4, NULL, 0)); } ;
 
 registers: REGISTER STRING /* == regname */ EQUALS STRING /* == regval */
-	{
-		struct reg *r = malloc(sizeof(struct reg));
-		memset (r, 0, sizeof(struct reg));
-		r->key = $<string>2;
-		r->value = $<string>4;
-		if (cur_parent->reg) {
-			struct reg *head = cur_parent->reg;
-			// sorting to be equal to sconfig's behaviour
-			int sort = strcmp(r->key, head->key);
-			if (sort == 0) {
-				printf("ERROR: duplicate 'register' key.\n");
-				exit(1);
-			}
-			if (sort<0) {
-				r->next = head;
-				cur_parent->reg = r;
-			} else {
-				while ((head->next) && (strcmp(head->next->key, r->key)<0)) head = head->next;
-				r->next = head->next;
-				head->next = r;
-			}
-		} else {
-			cur_parent->reg = r;
-		}
-	}
-	;
+	{ add_register($<string>2, $<string>4); } ;
 
 %%
-void pass0(FILE *fil, struct device *ptr) {
-	if ((ptr->type == device) && (ptr->id != 0) && (!ptr->used))
-		fprintf(fil, "struct device %s;\n", ptr->name);
-	if ((ptr->type == device) && (ptr->id != 0) && ptr->used)
-		fprintf(fil, "struct device %s;\n", ptr->aliased_name);
-}
-
-void pass1(FILE *fil, struct device *ptr) {
-	if (!ptr->used && (ptr->type == device)) {
-		fprintf(fil, "struct device %s = {\n", ptr->name);
-		fprintf(fil, "\t.ops = %s,\n", (ptr->ops)?(ptr->ops):"0");
-		fprintf(fil, "\t.bus = &%s.link[%d],\n", ptr->bus->name, ptr->bus->link);
-		fprintf(fil, "\t.path = {");
-		fprintf(fil, ptr->path, ptr->path_a, ptr->path_b);
-		fprintf(fil, "},\n");
-		fprintf(fil, "\t.enabled = %d,\n", ptr->enabled);
-		fprintf(fil, "\t.on_mainboard = 1,\n");
-		if (ptr->rescnt > 0) {
-			fprintf(fil, "\t.resources = %d,\n", ptr->rescnt);
-			fprintf(fil, "\t.resource = {\n");
-			struct resource *r = ptr->res;
-			while (r) {
-				fprintf(fil, "\t\t{ .flags=IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_");
-				if (r->type == IRQ) fprintf(fil, "IRQ");
-				if (r->type == DRQ) fprintf(fil, "DRQ");
-				if (r->type == IO) fprintf(fil, "IO");
-				fprintf(fil, ", .index=0x%x, .base=0x%x},\n", r->index, r->base);
-				r = r->next;
-			}
-			fprintf(fil, "\t },\n");
-		}
-		int link = 0;
-		fprintf(fil, "\t.link = {\n");
-		if (ptr->multidev) {
-			struct device *d = ptr;
-			while (d) {
-				if (device_match(d, ptr)) {
-					fprintf(fil, "\t\t[%d] = {\n", d->link);
-					fprintf(fil, "\t\t\t.link = %d,\n", d->link);
-					fprintf(fil, "\t\t\t.dev = &%s,\n", d->name);
-					if (d->children)
-						fprintf(fil, "\t\t\t.children = &%s,\n", d->children->name);
-					fprintf(fil, "\t\t},\n");
-					link++;
-				}
-				d = d->next_sibling;
-			}
-		} else {
-			if (ptr->children) {
-				fprintf(fil, "\t\t[0] = {\n");
-				fprintf(fil, "\t\t\t.link = 0,\n");
-				fprintf(fil, "\t\t\t.dev = &%s,\n", ptr->name);
-				fprintf(fil, "\t\t\t.children = &%s,\n", ptr->children->name);
-				fprintf(fil, "\t\t},\n");
-				link++;
-			}
-		}
-		fprintf(fil, "\t},\n");
-		fprintf(fil, "\t.links = %d,\n", link);
-		if (ptr->sibling)
-			fprintf(fil, "\t.sibling = &%s,\n", ptr->sibling->name);
-		if (ptr->chip->chiph_exists) {
-			fprintf(fil, "\t.chip_ops = &%s_ops,\n", ptr->chip->name_underscore);
-			fprintf(fil, "\t.chip_info = &%s_info_%d,\n", ptr->chip->name_underscore, ptr->chip->id);
-		}
-		if (ptr->nextdev)
-			fprintf(fil, "\t.next=&%s\n", ptr->nextdev->name);
-		fprintf(fil, "};\n");
-	}
-	if ((ptr->type == chip) && (ptr->chiph_exists)) {
-		if (ptr->reg) {
-			fprintf(fil, "struct %s_config %s_info_%d\t= {\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
-			struct reg *r = ptr->reg;
-			while (r) {
-				fprintf(fil, "\t.%s = %s,\n", r->key, r->value);
-				r = r->next;
-			}
-			fprintf(fil, "};\n\n");
-		} else {
-			fprintf(fil, "struct %s_config %s_info_%d;\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
-		}
-	}
-}
-
-void walk_device_tree(FILE *fil, struct device *ptr, void (*func)(FILE *, struct device*), struct device *chips) {
-	do {
-		func(fil, ptr);
-		ptr = ptr->next_sibling;
-	} while (ptr);
-}
-
-struct device mainboard = {
-	.name = "mainboard",
-	.name_underscore = "mainboard",
-	.id = 0,
-	.chip = &mainboard,
-	.type = chip,
-	.chiph_exists = 1,
-	.children = &root
-};
-
-struct device root = {
-	.name = "dev_root",
-	.name_underscore = "dev_root",
-	.id = 0,
-	.chip = &mainboard,
-	.type = device,
-	.path = " .type = DEVICE_PATH_ROOT ",
-	.ops = "&default_dev_ops_root",
-	.parent = &root,
-	.bus = &root,
-	.enabled = 1
-};
-
-int main(int argc, char** argv) {
-	if (argc != 3) {
-		printf("usage: sconfig vendor/mainboard outputdir\n");
-		return 1;
-	}
-	char *mainboard=argv[1];
-	char *outputdir=argv[2];
-	char *devtree=malloc(strlen(mainboard)+30);
-	char *outputc=malloc(strlen(outputdir)+10);
-	sprintf(devtree, "src/mainboard/%s/devicetree.cb", mainboard);
-	sprintf(outputc, "%s/static.c", outputdir);
-
-	headers.next = malloc(sizeof(struct header));
-	headers.next->name = malloc(strlen(mainboard)+12);
-	headers.next->next = 0;
-	sprintf(headers.next->name, "mainboard/%s", mainboard);
-
-	FILE *filec = fopen(devtree, "r");
-	yyrestart(filec);
-
-	FILE *staticc = fopen(outputc, "w");
-
-	cur_bus = cur_parent = lastdev = head = &root;
-	yyparse();
-	fclose(filec);
-
-	if ((head->type == chip) && (!head->chiph_exists)) {
-		struct device *tmp = head;
-		head = &root;
-		while (head->next != tmp) head = head->next;
-	}
-
-	fprintf(staticc, "#include <device/device.h>\n");
-	fprintf(staticc, "#include <device/pci.h>\n");
-	struct header *h = &headers;
-	while (h->next) {
-		h = h->next;
-		fprintf(staticc, "#include \"%s/chip.h\"\n", h->name);
-	}
-	fprintf(staticc, "\n/* pass 0 */\n");
-	walk_device_tree(staticc, &root, pass0, NULL);
-	fprintf(staticc, "\n/* pass 1 */\nstruct mainboard_config mainboard_info_0;\nstruct device **last_dev_p = &%s.next;\n", lastdev->name);
-	walk_device_tree(staticc, &root, pass1, NULL);
-
-	fclose(staticc);
-	return 0;
-}
Index: util/sconfig/Makefile.inc
===================================================================
--- util/sconfig/Makefile.inc	(revision 5522)
+++ util/sconfig/Makefile.inc	(working copy)
@@ -1,10 +1,17 @@ 
 sconfigobj :=
 sconfigobj += lex.yy.o
 sconfigobj += sconfig.tab.o
+sconfigobj += main.o
 
+SCONFIGFLAGS += -I$(top)/util/sconfig -I$(objutil)/sconfig
+
 $(objutil)/sconfig:
 	mkdir -p $@
 
+$(objutil)/sconfig/%.o: util/sconfig/%.c
+	printf "    HOSTCC     $(subst $(obj)/,,$(@))\n"
+	$(HOSTCC) $(SCONFIGFLAGS) $(HOSTCFLAGS) -c -o $@ $<
+
 $(objutil)/sconfig/%.o: $(objutil)/sconfig/%.c
 	printf "    HOSTCC     $(subst $(obj)/,,$(@))\n"
 	$(HOSTCC) $(SCONFIGFLAGS) $(HOSTCFLAGS) -c -o $@ $<
Index: util/sconfig/main.c
===================================================================
--- util/sconfig/main.c	(revision 5522)
+++ util/sconfig/main.c	(working copy)
@@ -1,4 +1,3 @@ 
-%{
 /*
  * sconfig, coreboot device tree compiler
  *
@@ -19,71 +18,40 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
+#include "sconfig.h"
+#include "sconfig.tab.h"
 
-enum devtype { chip, device };
+struct device *head, *lastdev;
 
-struct resource;
-struct resource {
-	int type;
-	int index;
-	int base;
-	struct resource *next;
+struct header headers;
+
+static int devcount = 0;
+
+static struct device root;
+static struct device mainboard = {
+	.name = "mainboard",
+	.name_underscore = "mainboard",
+	.id = 0,
+	.chip = &mainboard,
+	.type = chip,
+	.chiph_exists = 1,
+	.children = &root
 };
 
-struct reg;
-struct reg {
-	char *key;
-	char *value;
-	struct reg *next;
+static struct device root = {
+	.name = "dev_root",
+	.name_underscore = "dev_root",
+	.id = 0,
+	.chip = &mainboard,
+	.type = device,
+	.path = " .type = DEVICE_PATH_ROOT ",
+	.ops = "&default_dev_ops_root",
+	.parent = &root,
+	.bus = &root,
+	.enabled = 1
 };
 
-struct device;
-struct device {
-	int id;
-	int enabled;
-	int used;
-	int multidev;
-	int link;
-	int rescnt;
-	int chiph_exists;
-	char *ops;
-	char *name;
-	char *aliased_name;
-	char *name_underscore;
-	char *path;
-	int path_a;
-	int path_b;
-	int bustype;
-	enum devtype type;
-	struct device *parent;
-	struct device *bus;
-	struct device *next;
-	struct device *nextdev;
-	struct device *children;
-	struct device *latestchild;
-	struct device *next_sibling;
-	struct device *sibling;
-	struct device *chip;
-	struct resource *res;
-	struct reg *reg;
-} *head, *lastdev, *cur_parent, *cur_bus, root;
-
-struct header;
-struct header {
-	char *name;
-	struct header *next;
-} headers;
-
-int devcount = 0;
-
-struct device *new_dev() {
+static struct device *new_dev() {
 	struct device *dev = malloc(sizeof(struct device));
 	memset(dev, 0, sizeof(struct device));
 	dev->id = ++devcount;
@@ -94,7 +62,7 @@ 
 	return dev;
 }
 
-int device_match(struct device *a, struct device *b) {
+static int device_match(struct device *a, struct device *b) {
 	if ((a->bustype == b->bustype) && (a->bus == b->bus) && (a->path_a == b->path_a) && (a->path_b == b->path_b))
 		return 1;
 	return 0;
@@ -121,15 +89,8 @@ 
 {
 	fprintf (stderr, "%s\n", str);
 }
-%}
-%union {
-	struct device *device;
-	char *string;
-	int number;
-}
-%token CHIP DEVICE REGISTER BOOL BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC APIC_CLUSTER PCI_DOMAIN IRQ DRQ IO NUMBER
-%%
-devtree: devchip {
+
+void postprocess_devtree(void) {
 	root.next_sibling = root.children;
 	root.next_sibling->next_sibling = root.next_sibling->children;
 
@@ -147,53 +108,43 @@ 
 		while (dev->nextdev && dev->nextdev->used) dev->nextdev = dev->nextdev->nextdev;
 		dev = dev->next_sibling;
 	}
-	};
+}
 
-devchip: chip | device ;
-
-devices: devices devchip | devices registers | ;
-
-devicesorresources: devicesorresources devchip | devicesorresources resource | ;
-
-chip: CHIP STRING /* == path */ {
-	$<device>$ = new_dev();
-	$<device>$->chiph_exists = 1;
-	$<device>$->name = $<string>2;
-	$<device>$->name_underscore = strdup($<device>$->name);
+struct device *new_chip(char *path) {
+	struct device *new_chip = new_dev();
+	new_chip->chiph_exists = 1;
+	new_chip->name = path;
+	new_chip->name_underscore = strdup(new_chip->name);
 	char *c;
-	for (c = $<device>$->name_underscore; *c; c++) {
+	for (c = new_chip->name_underscore; *c; c++) {
 		if (*c == '/') *c = '_';
 		if (*c == '-') *c = '_';
 	}
-	$<device>$->type = chip;
-	$<device>$->chip = $<device>$;
+	new_chip->type = chip;
+	new_chip->chip = new_chip;
 
 	struct stat st;
-	char *chip_h = malloc(strlen($<string>2)+12);
-	sprintf(chip_h, "src/%s/chip.h", $<string>2);
+	char *chip_h = malloc(strlen(path)+12);
+	sprintf(chip_h, "src/%s/chip.h", path);
 	if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
-		$<device>$->chiph_exists = 0;
+		new_chip->chiph_exists = 0;
 
 	if (cur_parent->latestchild) {
-		cur_parent->latestchild->next_sibling = $<device>$;
-		cur_parent->latestchild->sibling = $<device>$;
+		cur_parent->latestchild->next_sibling = new_chip;
+		cur_parent->latestchild->sibling = new_chip;
 	}
-	cur_parent->latestchild = $<device>$;
+	cur_parent->latestchild = new_chip;
 	if (!cur_parent->children)
-		cur_parent->children = $<device>$;
-
-	cur_parent = $<device>$;
+		cur_parent->children = new_chip;
+	return new_chip;
 }
-	devices END {
-	cur_parent = $<device>3->parent;
 
-	fold_in($<device>3);
-
-	if ($<device>3->chiph_exists) {
+void add_header(struct device *dev) {
+	if (dev->chiph_exists) {
 		int include_exists = 0;
 		struct header *h = &headers;
 		while (h->next) {
-			int result = strcmp($<device>3->name, h->next->name);
+			int result = strcmp(dev->name, h->next->name);
 			if (result == 0) {
 				include_exists = 1;
 				break;
@@ -205,70 +156,63 @@ 
 			struct header *tmp = h->next;
 			h->next = malloc(sizeof(struct header));
 			memset(h->next, 0, sizeof(struct header));
-			h->next->name = $<device>3->name;
+			h->next->name = dev->name;
 			h->next->next = tmp;
-			break;
 		}
 	}
-};
+}
 
-device: DEVICE BUS NUMBER /* == devnum */ BOOL {
-	$<device>$ = new_dev();
-	$<device>$->bustype = $<number>2;
+struct device *new_device(const int bus, const char *devnum, int enabled) {
+	struct device *new_d = new_dev();
+	new_d->bustype = bus;
 
 	char *tmp;
-	$<device>$->path_a = strtol(strdup($<string>3), &tmp, 16);
+	new_d->path_a = strtol(strdup(devnum), &tmp, 16);
 	if (*tmp == '.') {
 		tmp++;
-		$<device>$->path_b = strtol(tmp, NULL, 16);
+		new_d->path_b = strtol(tmp, NULL, 16);
 	}
 
 	char *name = malloc(10);
-	sprintf(name, "_dev%d", $<device>$->id);
-	$<device>$->name = name;
-	$<device>$->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr
-	$<device>$->type = device;
-	$<device>$->enabled = $<number>4;
-	$<device>$->chip = $<device>$->parent->chip;
+	sprintf(name, "_dev%d", new_d->id);
+	new_d->name = name;
+	new_d->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr
+	new_d->type = device;
+	new_d->enabled = enabled;
+	new_d->chip = new_d->parent->chip;
 
 	if (cur_parent->latestchild) {
-		cur_parent->latestchild->next_sibling = $<device>$;
-		cur_parent->latestchild->sibling = $<device>$;
+		cur_parent->latestchild->next_sibling = new_d;
+		cur_parent->latestchild->sibling = new_d;
 	}
-	cur_parent->latestchild = $<device>$;
+	cur_parent->latestchild = new_d;
 	if (!cur_parent->children)
-		cur_parent->children = $<device>$;
+		cur_parent->children = new_d;
 
-	lastdev->nextdev = $<device>$;
-	lastdev = $<device>$;
-	if ($<number>2 == PCI) {
-		$<device>$->path = ".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}";
+	lastdev->nextdev = new_d;
+	lastdev = new_d;
+	if (bus == PCI) {
+		new_d->path = ".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}";
 	}
-	if ($<number>2 == PNP) {
-		$<device>$->path = ".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}";
+	if (bus == PNP) {
+		new_d->path = ".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}";
 	}
-	if ($<number>2 == I2C) {
-		$<device>$->path = ".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}";
+	if (bus == I2C) {
+		new_d->path = ".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}";
 	}
-	if ($<number>2 == APIC) {
-		$<device>$->path = ".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}";
+	if (bus == APIC) {
+		new_d->path = ".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}";
 	}
-	if ($<number>2 == APIC_CLUSTER) {
-		$<device>$->path = ".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}";
+	if (bus == APIC_CLUSTER) {
+		new_d->path = ".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}";
 	}
-	if ($<number>2 == PCI_DOMAIN) {
-		$<device>$->path = ".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}";
+	if (bus == PCI_DOMAIN) {
+		new_d->path = ".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}";
 	}
-	cur_parent = $<device>$;
-	cur_bus = $<device>$;
+	return new_d;
 }
-	devicesorresources END {
-	cur_parent = $<device>5->parent;
-	cur_bus = $<device>5->bus;
 
-	fold_in($<device>5);
-
-	struct device *d = $<device>5->children;
+void alias_siblings(struct device *d) {
 	while (d) {
 		int link = 0;
 		struct device *cmp = d->next_sibling;
@@ -289,63 +233,58 @@ 
 		}
 		d = d->next_sibling;
 	}
-};
+}
 
-resource: RESOURCE NUMBER /* == resnum */ EQUALS NUMBER /* == resval */
-	{
-		struct resource *r = malloc(sizeof(struct resource));
-		memset (r, 0, sizeof(struct resource));
-		r->type = $<number>1;
-		r->index = strtol($<string>2, NULL, 0);
-		r->base = strtol($<string>4, NULL, 0);
-		if (cur_parent->res) {
-			struct resource *head = cur_parent->res;
-			while (head->next) head = head->next;
-			head->next = r;
-		} else {
-			cur_parent->res = r;
-		}
-		cur_parent->rescnt++;
+void add_resource(int type, int index, int base) {
+	struct resource *r = malloc(sizeof(struct resource));
+	memset (r, 0, sizeof(struct resource));
+	r->type = type;
+	r->index = index;
+	r->base = base;
+	if (cur_parent->res) {
+		struct resource *head = cur_parent->res;
+		while (head->next) head = head->next;
+		head->next = r;
+	} else {
+		cur_parent->res = r;
 	}
-	;
+	cur_parent->rescnt++;
+}
 
-registers: REGISTER STRING /* == regname */ EQUALS STRING /* == regval */
-	{
-		struct reg *r = malloc(sizeof(struct reg));
-		memset (r, 0, sizeof(struct reg));
-		r->key = $<string>2;
-		r->value = $<string>4;
-		if (cur_parent->reg) {
-			struct reg *head = cur_parent->reg;
-			// sorting to be equal to sconfig's behaviour
-			int sort = strcmp(r->key, head->key);
-			if (sort == 0) {
-				printf("ERROR: duplicate 'register' key.\n");
-				exit(1);
-			}
-			if (sort<0) {
-				r->next = head;
-				cur_parent->reg = r;
-			} else {
-				while ((head->next) && (strcmp(head->next->key, r->key)<0)) head = head->next;
-				r->next = head->next;
-				head->next = r;
-			}
-		} else {
+void add_register(char *name, char *val) {
+	struct reg *r = malloc(sizeof(struct reg));
+	memset (r, 0, sizeof(struct reg));
+	r->key = name;
+	r->value = val;
+	if (cur_parent->reg) {
+		struct reg *head = cur_parent->reg;
+		// sorting to be equal to sconfig's behaviour
+		int sort = strcmp(r->key, head->key);
+		if (sort == 0) {
+			printf("ERROR: duplicate 'register' key.\n");
+			exit(1);
+		}
+		if (sort<0) {
+			r->next = head;
 			cur_parent->reg = r;
+		} else {
+			while ((head->next) && (strcmp(head->next->key, r->key)<0)) head = head->next;
+			r->next = head->next;
+			head->next = r;
 		}
+	} else {
+		cur_parent->reg = r;
 	}
-	;
+}
 
-%%
-void pass0(FILE *fil, struct device *ptr) {
+static void pass0(FILE *fil, struct device *ptr) {
 	if ((ptr->type == device) && (ptr->id != 0) && (!ptr->used))
 		fprintf(fil, "struct device %s;\n", ptr->name);
 	if ((ptr->type == device) && (ptr->id != 0) && ptr->used)
 		fprintf(fil, "struct device %s;\n", ptr->aliased_name);
 }
 
-void pass1(FILE *fil, struct device *ptr) {
+static void pass1(FILE *fil, struct device *ptr) {
 	if (!ptr->used && (ptr->type == device)) {
 		fprintf(fil, "struct device %s = {\n", ptr->name);
 		fprintf(fil, "\t.ops = %s,\n", (ptr->ops)?(ptr->ops):"0");
@@ -422,36 +361,13 @@ 
 	}
 }
 
-void walk_device_tree(FILE *fil, struct device *ptr, void (*func)(FILE *, struct device*), struct device *chips) {
+static void walk_device_tree(FILE *fil, struct device *ptr, void (*func)(FILE *, struct device*), struct device *chips) {
 	do {
 		func(fil, ptr);
 		ptr = ptr->next_sibling;
 	} while (ptr);
 }
 
-struct device mainboard = {
-	.name = "mainboard",
-	.name_underscore = "mainboard",
-	.id = 0,
-	.chip = &mainboard,
-	.type = chip,
-	.chiph_exists = 1,
-	.children = &root
-};
-
-struct device root = {
-	.name = "dev_root",
-	.name_underscore = "dev_root",
-	.id = 0,
-	.chip = &mainboard,
-	.type = device,
-	.path = " .type = DEVICE_PATH_ROOT ",
-	.ops = "&default_dev_ops_root",
-	.parent = &root,
-	.bus = &root,
-	.enabled = 1
-};
-
 int main(int argc, char** argv) {
 	if (argc != 3) {
 		printf("usage: sconfig vendor/mainboard outputdir\n");
Index: util/sconfig/sconfig.tab.c_shipped
===================================================================
--- util/sconfig/sconfig.tab.c_shipped	(revision 5522)
+++ util/sconfig/sconfig.tab.c_shipped	(working copy)
@@ -2,20 +2,20 @@ 
 /* A Bison parser, made by GNU Bison 2.4.1.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
-
+   
       Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
-
+   
    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 3 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, see <http://www.gnu.org/licenses/>.  */
 
@@ -28,7 +28,7 @@ 
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -88,111 +88,13 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
+#include "sconfig.h"
 
-enum devtype { chip, device };
+struct device *cur_parent, *cur_bus;
 
-struct resource;
-struct resource {
-	int type;
-	int index;
-	int base;
-	struct resource *next;
-};
 
-struct reg;
-struct reg {
-	char *key;
-	char *value;
-	struct reg *next;
-};
 
-struct device;
-struct device {
-	int id;
-	int enabled;
-	int used;
-	int multidev;
-	int link;
-	int rescnt;
-	int chiph_exists;
-	char *ops;
-	char *name;
-	char *aliased_name;
-	char *name_underscore;
-	char *path;
-	int path_a;
-	int path_b;
-	int bustype;
-	enum devtype type;
-	struct device *parent;
-	struct device *bus;
-	struct device *next;
-	struct device *nextdev;
-	struct device *children;
-	struct device *latestchild;
-	struct device *next_sibling;
-	struct device *sibling;
-	struct device *chip;
-	struct resource *res;
-	struct reg *reg;
-} *head, *lastdev, *cur_parent, *cur_bus, root;
 
-struct header;
-struct header {
-	char *name;
-	struct header *next;
-} headers;
-
-int devcount = 0;
-
-struct device *new_dev() {
-	struct device *dev = malloc(sizeof(struct device));
-	memset(dev, 0, sizeof(struct device));
-	dev->id = ++devcount;
-	dev->parent = cur_parent;
-	dev->bus = cur_bus;
-	head->next = dev;
-	head = dev;
-	return dev;
-}
-
-int device_match(struct device *a, struct device *b) {
-	if ((a->bustype == b->bustype) && (a->bus == b->bus) && (a->path_a == b->path_a) && (a->path_b == b->path_b))
-		return 1;
-	return 0;
-}
-
-void fold_in(struct device *parent) {
-	struct device *child = parent->children;
-	struct device *latest = 0;
-	while (child != latest) {
-		if (child->children) {
-			if (!latest) latest = child->children;
-			parent->latestchild->next_sibling = child->children;
-			parent->latestchild = child->latestchild;
-		}
-		child = child->next_sibling;
-	}
-}
-
-int yywrap(void) {
-	return 1;
-}
-
-void yyerror (char const *str)
-{
-	fprintf (stderr, "%s\n", str);
-}
-
-
-
 /* Enabling traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 0
@@ -549,10 +451,10 @@ 
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
+static const yytype_uint8 yyrline[] =
 {
-       0,   132,   132,   152,   152,   154,   154,   154,   156,   156,
-     156,   158,   158,   215,   215,   294,   312
+       0,    34,    34,    36,    36,    38,    38,    38,    40,    40,
+      40,    42,    42,    52,    52,    64,    67
 };
 #endif
 
@@ -1466,56 +1368,13 @@ 
     {
         case 2:
 
-    {
-	root.next_sibling = root.children;
-	root.next_sibling->next_sibling = root.next_sibling->children;
-
-	struct device *dev = &root;
-	while (dev) {
-		/* skip "chip" elements in children chain */
-		while (dev->children && (dev->children->type == chip)) dev->children = dev->children->children;
-		/* skip "chip" elements and functions of the same device in sibling chain */
-		while (dev->sibling && dev->sibling->used) dev->sibling = dev->sibling->sibling;
-		/* If end of chain, and parent is a chip, move on */
-		if (!dev->sibling && (dev->parent->type == chip)) dev->sibling = dev->parent->sibling;
-		/* skip chips */
-		while (dev->sibling && dev->sibling->type == chip) dev->sibling = dev->sibling->children;
-		/* skip duplicate function elements in nextdev chain */
-		while (dev->nextdev && dev->nextdev->used) dev->nextdev = dev->nextdev->nextdev;
-		dev = dev->next_sibling;
-	}
-	;}
+    { postprocess_devtree(); ;}
     break;
 
   case 11:
 
     {
-	(yyval.device) = new_dev();
-	(yyval.device)->chiph_exists = 1;
-	(yyval.device)->name = (yyvsp[(2) - (2)].string);
-	(yyval.device)->name_underscore = strdup((yyval.device)->name);
-	char *c;
-	for (c = (yyval.device)->name_underscore; *c; c++) {
-		if (*c == '/') *c = '_';
-		if (*c == '-') *c = '_';
-	}
-	(yyval.device)->type = chip;
-	(yyval.device)->chip = (yyval.device);
-
-	struct stat st;
-	char *chip_h = malloc(strlen((yyvsp[(2) - (2)].string))+12);
-	sprintf(chip_h, "src/%s/chip.h", (yyvsp[(2) - (2)].string));
-	if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
-		(yyval.device)->chiph_exists = 0;
-
-	if (cur_parent->latestchild) {
-		cur_parent->latestchild->next_sibling = (yyval.device);
-		cur_parent->latestchild->sibling = (yyval.device);
-	}
-	cur_parent->latestchild = (yyval.device);
-	if (!cur_parent->children)
-		cur_parent->children = (yyval.device);
-
+	(yyval.device) = new_chip((yyvsp[(2) - (2)].string));
 	cur_parent = (yyval.device);
 ;}
     break;
@@ -1524,82 +1383,15 @@ 
 
     {
 	cur_parent = (yyvsp[(3) - (5)].device)->parent;
-
 	fold_in((yyvsp[(3) - (5)].device));
-
-	if ((yyvsp[(3) - (5)].device)->chiph_exists) {
-		int include_exists = 0;
-		struct header *h = &headers;
-		while (h->next) {
-			int result = strcmp((yyvsp[(3) - (5)].device)->name, h->next->name);
-			if (result == 0) {
-				include_exists = 1;
-				break;
-			}
-			if (result < 0) break;
-			h = h->next;
-		}
-		if (!include_exists) {
-			struct header *tmp = h->next;
-			h->next = malloc(sizeof(struct header));
-			memset(h->next, 0, sizeof(struct header));
-			h->next->name = (yyvsp[(3) - (5)].device)->name;
-			h->next->next = tmp;
-			break;
-		}
-	}
+	add_header((yyvsp[(3) - (5)].device));
 ;}
     break;
 
   case 13:
 
     {
-	(yyval.device) = new_dev();
-	(yyval.device)->bustype = (yyvsp[(2) - (4)].number);
-
-	char *tmp;
-	(yyval.device)->path_a = strtol(strdup((yyvsp[(3) - (4)].string)), &tmp, 16);
-	if (*tmp == '.') {
-		tmp++;
-		(yyval.device)->path_b = strtol(tmp, NULL, 16);
-	}
-
-	char *name = malloc(10);
-	sprintf(name, "_dev%d", (yyval.device)->id);
-	(yyval.device)->name = name;
-	(yyval.device)->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr
-	(yyval.device)->type = device;
-	(yyval.device)->enabled = (yyvsp[(4) - (4)].number);
-	(yyval.device)->chip = (yyval.device)->parent->chip;
-
-	if (cur_parent->latestchild) {
-		cur_parent->latestchild->next_sibling = (yyval.device);
-		cur_parent->latestchild->sibling = (yyval.device);
-	}
-	cur_parent->latestchild = (yyval.device);
-	if (!cur_parent->children)
-		cur_parent->children = (yyval.device);
-
-	lastdev->nextdev = (yyval.device);
-	lastdev = (yyval.device);
-	if ((yyvsp[(2) - (4)].number) == PCI) {
-		(yyval.device)->path = ".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}";
-	}
-	if ((yyvsp[(2) - (4)].number) == PNP) {
-		(yyval.device)->path = ".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}";
-	}
-	if ((yyvsp[(2) - (4)].number) == I2C) {
-		(yyval.device)->path = ".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}";
-	}
-	if ((yyvsp[(2) - (4)].number) == APIC) {
-		(yyval.device)->path = ".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}";
-	}
-	if ((yyvsp[(2) - (4)].number) == APIC_CLUSTER) {
-		(yyval.device)->path = ".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}";
-	}
-	if ((yyvsp[(2) - (4)].number) == PCI_DOMAIN) {
-		(yyval.device)->path = ".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}";
-	}
+	(yyval.device) = new_device((yyvsp[(2) - (4)].number), (yyvsp[(3) - (4)].string), (yyvsp[(4) - (4)].number));
 	cur_parent = (yyval.device);
 	cur_bus = (yyval.device);
 ;}
@@ -1610,79 +1402,19 @@ 
     {
 	cur_parent = (yyvsp[(5) - (7)].device)->parent;
 	cur_bus = (yyvsp[(5) - (7)].device)->bus;
-
 	fold_in((yyvsp[(5) - (7)].device));
-
-	struct device *d = (yyvsp[(5) - (7)].device)->children;
-	while (d) {
-		int link = 0;
-		struct device *cmp = d->next_sibling;
-		while (cmp && (cmp->bus == d->bus) && (cmp->path_a == d->path_a) && (cmp->path_b == d->path_b)) {
-			if (cmp->type==device && !cmp->used) {
-				if (device_match(d, cmp)) {
-					d->multidev = 1;
-
-					cmp->aliased_name = malloc(12);
-					sprintf(cmp->aliased_name, "_dev%d", cmp->id);
-					cmp->id = d->id;
-					cmp->name = d->name;
-					cmp->used = 1;
-					cmp->link = ++link;
-				}
-			}
-			cmp = cmp->next_sibling;
-		}
-		d = d->next_sibling;
-	}
+	alias_siblings((yyvsp[(5) - (7)].device)->children);
 ;}
     break;
 
   case 15:
 
-    {
-		struct resource *r = malloc(sizeof(struct resource));
-		memset (r, 0, sizeof(struct resource));
-		r->type = (yyvsp[(1) - (4)].number);
-		r->index = strtol((yyvsp[(2) - (4)].string), NULL, 0);
-		r->base = strtol((yyvsp[(4) - (4)].string), NULL, 0);
-		if (cur_parent->res) {
-			struct resource *head = cur_parent->res;
-			while (head->next) head = head->next;
-			head->next = r;
-		} else {
-			cur_parent->res = r;
-		}
-		cur_parent->rescnt++;
-	;}
+    { add_resource((yyvsp[(1) - (4)].number), strtol((yyvsp[(2) - (4)].string), NULL, 0), strtol((yyvsp[(4) - (4)].string), NULL, 0)); ;}
     break;
 
   case 16:
 
-    {
-		struct reg *r = malloc(sizeof(struct reg));
-		memset (r, 0, sizeof(struct reg));
-		r->key = (yyvsp[(2) - (4)].string);
-		r->value = (yyvsp[(4) - (4)].string);
-		if (cur_parent->reg) {
-			struct reg *head = cur_parent->reg;
-			// sorting to be equal to sconfig's behaviour
-			int sort = strcmp(r->key, head->key);
-			if (sort == 0) {
-				printf("ERROR: duplicate 'register' key.\n");
-				exit(1);
-			}
-			if (sort<0) {
-				r->next = head;
-				cur_parent->reg = r;
-			} else {
-				while ((head->next) && (strcmp(head->next->key, r->key)<0)) head = head->next;
-				r->next = head->next;
-				head->next = r;
-			}
-		} else {
-			cur_parent->reg = r;
-		}
-	;}
+    { add_register((yyvsp[(2) - (4)].string), (yyvsp[(4) - (4)].string)); ;}
     break;
 
 
@@ -1898,165 +1630,4 @@ 
 
 
 
-void pass0(FILE *fil, struct device *ptr) {
-	if ((ptr->type == device) && (ptr->id != 0) && (!ptr->used))
-		fprintf(fil, "struct device %s;\n", ptr->name);
-	if ((ptr->type == device) && (ptr->id != 0) && ptr->used)
-		fprintf(fil, "struct device %s;\n", ptr->aliased_name);
-}
 
-void pass1(FILE *fil, struct device *ptr) {
-	if (!ptr->used && (ptr->type == device)) {
-		fprintf(fil, "struct device %s = {\n", ptr->name);
-		fprintf(fil, "\t.ops = %s,\n", (ptr->ops)?(ptr->ops):"0");
-		fprintf(fil, "\t.bus = &%s.link[%d],\n", ptr->bus->name, ptr->bus->link);
-		fprintf(fil, "\t.path = {");
-		fprintf(fil, ptr->path, ptr->path_a, ptr->path_b);
-		fprintf(fil, "},\n");
-		fprintf(fil, "\t.enabled = %d,\n", ptr->enabled);
-		fprintf(fil, "\t.on_mainboard = 1,\n");
-		if (ptr->rescnt > 0) {
-			fprintf(fil, "\t.resources = %d,\n", ptr->rescnt);
-			fprintf(fil, "\t.resource = {\n");
-			struct resource *r = ptr->res;
-			while (r) {
-				fprintf(fil, "\t\t{ .flags=IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_");
-				if (r->type == IRQ) fprintf(fil, "IRQ");
-				if (r->type == DRQ) fprintf(fil, "DRQ");
-				if (r->type == IO) fprintf(fil, "IO");
-				fprintf(fil, ", .index=0x%x, .base=0x%x},\n", r->index, r->base);
-				r = r->next;
-			}
-			fprintf(fil, "\t },\n");
-		}
-		int link = 0;
-		fprintf(fil, "\t.link = {\n");
-		if (ptr->multidev) {
-			struct device *d = ptr;
-			while (d) {
-				if (device_match(d, ptr)) {
-					fprintf(fil, "\t\t[%d] = {\n", d->link);
-					fprintf(fil, "\t\t\t.link = %d,\n", d->link);
-					fprintf(fil, "\t\t\t.dev = &%s,\n", d->name);
-					if (d->children)
-						fprintf(fil, "\t\t\t.children = &%s,\n", d->children->name);
-					fprintf(fil, "\t\t},\n");
-					link++;
-				}
-				d = d->next_sibling;
-			}
-		} else {
-			if (ptr->children) {
-				fprintf(fil, "\t\t[0] = {\n");
-				fprintf(fil, "\t\t\t.link = 0,\n");
-				fprintf(fil, "\t\t\t.dev = &%s,\n", ptr->name);
-				fprintf(fil, "\t\t\t.children = &%s,\n", ptr->children->name);
-				fprintf(fil, "\t\t},\n");
-				link++;
-			}
-		}
-		fprintf(fil, "\t},\n");
-		fprintf(fil, "\t.links = %d,\n", link);
-		if (ptr->sibling)
-			fprintf(fil, "\t.sibling = &%s,\n", ptr->sibling->name);
-		if (ptr->chip->chiph_exists) {
-			fprintf(fil, "\t.chip_ops = &%s_ops,\n", ptr->chip->name_underscore);
-			fprintf(fil, "\t.chip_info = &%s_info_%d,\n", ptr->chip->name_underscore, ptr->chip->id);
-		}
-		if (ptr->nextdev)
-			fprintf(fil, "\t.next=&%s\n", ptr->nextdev->name);
-		fprintf(fil, "};\n");
-	}
-	if ((ptr->type == chip) && (ptr->chiph_exists)) {
-		if (ptr->reg) {
-			fprintf(fil, "struct %s_config %s_info_%d\t= {\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
-			struct reg *r = ptr->reg;
-			while (r) {
-				fprintf(fil, "\t.%s = %s,\n", r->key, r->value);
-				r = r->next;
-			}
-			fprintf(fil, "};\n\n");
-		} else {
-			fprintf(fil, "struct %s_config %s_info_%d;\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
-		}
-	}
-}
-
-void walk_device_tree(FILE *fil, struct device *ptr, void (*func)(FILE *, struct device*), struct device *chips) {
-	do {
-		func(fil, ptr);
-		ptr = ptr->next_sibling;
-	} while (ptr);
-}
-
-struct device mainboard = {
-	.name = "mainboard",
-	.name_underscore = "mainboard",
-	.id = 0,
-	.chip = &mainboard,
-	.type = chip,
-	.chiph_exists = 1,
-	.children = &root
-};
-
-struct device root = {
-	.name = "dev_root",
-	.name_underscore = "dev_root",
-	.id = 0,
-	.chip = &mainboard,
-	.type = device,
-	.path = " .type = DEVICE_PATH_ROOT ",
-	.ops = "&default_dev_ops_root",
-	.parent = &root,
-	.bus = &root,
-	.enabled = 1
-};
-
-int main(int argc, char** argv) {
-	if (argc != 3) {
-		printf("usage: sconfig vendor/mainboard outputdir\n");
-		return 1;
-	}
-	char *mainboard=argv[1];
-	char *outputdir=argv[2];
-	char *devtree=malloc(strlen(mainboard)+30);
-	char *outputc=malloc(strlen(outputdir)+10);
-	sprintf(devtree, "src/mainboard/%s/devicetree.cb", mainboard);
-	sprintf(outputc, "%s/static.c", outputdir);
-
-	headers.next = malloc(sizeof(struct header));
-	headers.next->name = malloc(strlen(mainboard)+12);
-	headers.next->next = 0;
-	sprintf(headers.next->name, "mainboard/%s", mainboard);
-
-	FILE *filec = fopen(devtree, "r");
-	yyrestart(filec);
-
-	FILE *staticc = fopen(outputc, "w");
-
-	cur_bus = cur_parent = lastdev = head = &root;
-	yyparse();
-	fclose(filec);
-
-	if ((head->type == chip) && (!head->chiph_exists)) {
-		struct device *tmp = head;
-		head = &root;
-		while (head->next != tmp) head = head->next;
-	}
-
-	fprintf(staticc, "#include <device/device.h>\n");
-	fprintf(staticc, "#include <device/pci.h>\n");
-	struct header *h = &headers;
-	while (h->next) {
-		h = h->next;
-		fprintf(staticc, "#include \"%s/chip.h\"\n", h->name);
-	}
-	fprintf(staticc, "\n/* pass 0 */\n");
-	walk_device_tree(staticc, &root, pass0, NULL);
-	fprintf(staticc, "\n/* pass 1 */\nstruct mainboard_config mainboard_info_0;\nstruct device **last_dev_p = &%s.next;\n", lastdev->name);
-	walk_device_tree(staticc, &root, pass1, NULL);
-
-	fclose(staticc);
-	return 0;
-}
-
Index: util/sconfig/sconfig.h
===================================================================
--- util/sconfig/sconfig.h	(revision 5522)
+++ util/sconfig/sconfig.h	(working copy)
@@ -1,4 +1,3 @@ 
-%{
 /*
  * sconfig, coreboot device tree compiler
  *
@@ -73,429 +72,22 @@ 
 	struct device *chip;
 	struct resource *res;
 	struct reg *reg;
-} *head, *lastdev, *cur_parent, *cur_bus, root;
+};
 
+extern struct device *cur_parent, *cur_bus;
+
 struct header;
 struct header {
 	char *name;
 	struct header *next;
-} headers;
-
-int devcount = 0;
-
-struct device *new_dev() {
-	struct device *dev = malloc(sizeof(struct device));
-	memset(dev, 0, sizeof(struct device));
-	dev->id = ++devcount;
-	dev->parent = cur_parent;
-	dev->bus = cur_bus;
-	head->next = dev;
-	head = dev;
-	return dev;
-}
-
-int device_match(struct device *a, struct device *b) {
-	if ((a->bustype == b->bustype) && (a->bus == b->bus) && (a->path_a == b->path_a) && (a->path_b == b->path_b))
-		return 1;
-	return 0;
-}
-
-void fold_in(struct device *parent) {
-	struct device *child = parent->children;
-	struct device *latest = 0;
-	while (child != latest) {
-		if (child->children) {
-			if (!latest) latest = child->children;
-			parent->latestchild->next_sibling = child->children;
-			parent->latestchild = child->latestchild;
-		}
-		child = child->next_sibling;
-	}
-}
-
-int yywrap(void) {
-	return 1;
-}
-
-void yyerror (char const *str)
-{
-	fprintf (stderr, "%s\n", str);
-}
-%}
-%union {
-	struct device *device;
-	char *string;
-	int number;
-}
-%token CHIP DEVICE REGISTER BOOL BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC APIC_CLUSTER PCI_DOMAIN IRQ DRQ IO NUMBER
-%%
-devtree: devchip {
-	root.next_sibling = root.children;
-	root.next_sibling->next_sibling = root.next_sibling->children;
-
-	struct device *dev = &root;
-	while (dev) {
-		/* skip "chip" elements in children chain */
-		while (dev->children && (dev->children->type == chip)) dev->children = dev->children->children;
-		/* skip "chip" elements and functions of the same device in sibling chain */
-		while (dev->sibling && dev->sibling->used) dev->sibling = dev->sibling->sibling;
-		/* If end of chain, and parent is a chip, move on */
-		if (!dev->sibling && (dev->parent->type == chip)) dev->sibling = dev->parent->sibling;
-		/* skip chips */
-		while (dev->sibling && dev->sibling->type == chip) dev->sibling = dev->sibling->children;
-		/* skip duplicate function elements in nextdev chain */
-		while (dev->nextdev && dev->nextdev->used) dev->nextdev = dev->nextdev->nextdev;
-		dev = dev->next_sibling;
-	}
-	};
-
-devchip: chip | device ;
-
-devices: devices devchip | devices registers | ;
-
-devicesorresources: devicesorresources devchip | devicesorresources resource | ;
-
-chip: CHIP STRING /* == path */ {
-	$<device>$ = new_dev();
-	$<device>$->chiph_exists = 1;
-	$<device>$->name = $<string>2;
-	$<device>$->name_underscore = strdup($<device>$->name);
-	char *c;
-	for (c = $<device>$->name_underscore; *c; c++) {
-		if (*c == '/') *c = '_';
-		if (*c == '-') *c = '_';
-	}
-	$<device>$->type = chip;
-	$<device>$->chip = $<device>$;
-
-	struct stat st;
-	char *chip_h = malloc(strlen($<string>2)+12);
-	sprintf(chip_h, "src/%s/chip.h", $<string>2);
-	if ((stat(chip_h, &st) == -1) && (errno == ENOENT))
-		$<device>$->chiph_exists = 0;
-
-	if (cur_parent->latestchild) {
-		cur_parent->latestchild->next_sibling = $<device>$;
-		cur_parent->latestchild->sibling = $<device>$;
-	}
-	cur_parent->latestchild = $<device>$;
-	if (!cur_parent->children)
-		cur_parent->children = $<device>$;
-
-	cur_parent = $<device>$;
-}
-	devices END {
-	cur_parent = $<device>3->parent;
-
-	fold_in($<device>3);
-
-	if ($<device>3->chiph_exists) {
-		int include_exists = 0;
-		struct header *h = &headers;
-		while (h->next) {
-			int result = strcmp($<device>3->name, h->next->name);
-			if (result == 0) {
-				include_exists = 1;
-				break;
-			}
-			if (result < 0) break;
-			h = h->next;
-		}
-		if (!include_exists) {
-			struct header *tmp = h->next;
-			h->next = malloc(sizeof(struct header));
-			memset(h->next, 0, sizeof(struct header));
-			h->next->name = $<device>3->name;
-			h->next->next = tmp;
-			break;
-		}
-	}
 };
 
-device: DEVICE BUS NUMBER /* == devnum */ BOOL {
-	$<device>$ = new_dev();
-	$<device>$->bustype = $<number>2;
+void fold_in(struct device *parent);
 
-	char *tmp;
-	$<device>$->path_a = strtol(strdup($<string>3), &tmp, 16);
-	if (*tmp == '.') {
-		tmp++;
-		$<device>$->path_b = strtol(tmp, NULL, 16);
-	}
-
-	char *name = malloc(10);
-	sprintf(name, "_dev%d", $<device>$->id);
-	$<device>$->name = name;
-	$<device>$->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr
-	$<device>$->type = device;
-	$<device>$->enabled = $<number>4;
-	$<device>$->chip = $<device>$->parent->chip;
-
-	if (cur_parent->latestchild) {
-		cur_parent->latestchild->next_sibling = $<device>$;
-		cur_parent->latestchild->sibling = $<device>$;
-	}
-	cur_parent->latestchild = $<device>$;
-	if (!cur_parent->children)
-		cur_parent->children = $<device>$;
-
-	lastdev->nextdev = $<device>$;
-	lastdev = $<device>$;
-	if ($<number>2 == PCI) {
-		$<device>$->path = ".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}";
-	}
-	if ($<number>2 == PNP) {
-		$<device>$->path = ".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}";
-	}
-	if ($<number>2 == I2C) {
-		$<device>$->path = ".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}";
-	}
-	if ($<number>2 == APIC) {
-		$<device>$->path = ".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}";
-	}
-	if ($<number>2 == APIC_CLUSTER) {
-		$<device>$->path = ".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}";
-	}
-	if ($<number>2 == PCI_DOMAIN) {
-		$<device>$->path = ".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}";
-	}
-	cur_parent = $<device>$;
-	cur_bus = $<device>$;
-}
-	devicesorresources END {
-	cur_parent = $<device>5->parent;
-	cur_bus = $<device>5->bus;
-
-	fold_in($<device>5);
-
-	struct device *d = $<device>5->children;
-	while (d) {
-		int link = 0;
-		struct device *cmp = d->next_sibling;
-		while (cmp && (cmp->bus == d->bus) && (cmp->path_a == d->path_a) && (cmp->path_b == d->path_b)) {
-			if (cmp->type==device && !cmp->used) {
-				if (device_match(d, cmp)) {
-					d->multidev = 1;
-
-					cmp->aliased_name = malloc(12);
-					sprintf(cmp->aliased_name, "_dev%d", cmp->id);
-					cmp->id = d->id;
-					cmp->name = d->name;
-					cmp->used = 1;
-					cmp->link = ++link;
-				}
-			}
-			cmp = cmp->next_sibling;
-		}
-		d = d->next_sibling;
-	}
-};
-
-resource: RESOURCE NUMBER /* == resnum */ EQUALS NUMBER /* == resval */
-	{
-		struct resource *r = malloc(sizeof(struct resource));
-		memset (r, 0, sizeof(struct resource));
-		r->type = $<number>1;
-		r->index = strtol($<string>2, NULL, 0);
-		r->base = strtol($<string>4, NULL, 0);
-		if (cur_parent->res) {
-			struct resource *head = cur_parent->res;
-			while (head->next) head = head->next;
-			head->next = r;
-		} else {
-			cur_parent->res = r;
-		}
-		cur_parent->rescnt++;
-	}
-	;
-
-registers: REGISTER STRING /* == regname */ EQUALS STRING /* == regval */
-	{
-		struct reg *r = malloc(sizeof(struct reg));
-		memset (r, 0, sizeof(struct reg));
-		r->key = $<string>2;
-		r->value = $<string>4;
-		if (cur_parent->reg) {
-			struct reg *head = cur_parent->reg;
-			// sorting to be equal to sconfig's behaviour
-			int sort = strcmp(r->key, head->key);
-			if (sort == 0) {
-				printf("ERROR: duplicate 'register' key.\n");
-				exit(1);
-			}
-			if (sort<0) {
-				r->next = head;
-				cur_parent->reg = r;
-			} else {
-				while ((head->next) && (strcmp(head->next->key, r->key)<0)) head = head->next;
-				r->next = head->next;
-				head->next = r;
-			}
-		} else {
-			cur_parent->reg = r;
-		}
-	}
-	;
-
-%%
-void pass0(FILE *fil, struct device *ptr) {
-	if ((ptr->type == device) && (ptr->id != 0) && (!ptr->used))
-		fprintf(fil, "struct device %s;\n", ptr->name);
-	if ((ptr->type == device) && (ptr->id != 0) && ptr->used)
-		fprintf(fil, "struct device %s;\n", ptr->aliased_name);
-}
-
-void pass1(FILE *fil, struct device *ptr) {
-	if (!ptr->used && (ptr->type == device)) {
-		fprintf(fil, "struct device %s = {\n", ptr->name);
-		fprintf(fil, "\t.ops = %s,\n", (ptr->ops)?(ptr->ops):"0");
-		fprintf(fil, "\t.bus = &%s.link[%d],\n", ptr->bus->name, ptr->bus->link);
-		fprintf(fil, "\t.path = {");
-		fprintf(fil, ptr->path, ptr->path_a, ptr->path_b);
-		fprintf(fil, "},\n");
-		fprintf(fil, "\t.enabled = %d,\n", ptr->enabled);
-		fprintf(fil, "\t.on_mainboard = 1,\n");
-		if (ptr->rescnt > 0) {
-			fprintf(fil, "\t.resources = %d,\n", ptr->rescnt);
-			fprintf(fil, "\t.resource = {\n");
-			struct resource *r = ptr->res;
-			while (r) {
-				fprintf(fil, "\t\t{ .flags=IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_");
-				if (r->type == IRQ) fprintf(fil, "IRQ");
-				if (r->type == DRQ) fprintf(fil, "DRQ");
-				if (r->type == IO) fprintf(fil, "IO");
-				fprintf(fil, ", .index=0x%x, .base=0x%x},\n", r->index, r->base);
-				r = r->next;
-			}
-			fprintf(fil, "\t },\n");
-		}
-		int link = 0;
-		fprintf(fil, "\t.link = {\n");
-		if (ptr->multidev) {
-			struct device *d = ptr;
-			while (d) {
-				if (device_match(d, ptr)) {
-					fprintf(fil, "\t\t[%d] = {\n", d->link);
-					fprintf(fil, "\t\t\t.link = %d,\n", d->link);
-					fprintf(fil, "\t\t\t.dev = &%s,\n", d->name);
-					if (d->children)
-						fprintf(fil, "\t\t\t.children = &%s,\n", d->children->name);
-					fprintf(fil, "\t\t},\n");
-					link++;
-				}
-				d = d->next_sibling;
-			}
-		} else {
-			if (ptr->children) {
-				fprintf(fil, "\t\t[0] = {\n");
-				fprintf(fil, "\t\t\t.link = 0,\n");
-				fprintf(fil, "\t\t\t.dev = &%s,\n", ptr->name);
-				fprintf(fil, "\t\t\t.children = &%s,\n", ptr->children->name);
-				fprintf(fil, "\t\t},\n");
-				link++;
-			}
-		}
-		fprintf(fil, "\t},\n");
-		fprintf(fil, "\t.links = %d,\n", link);
-		if (ptr->sibling)
-			fprintf(fil, "\t.sibling = &%s,\n", ptr->sibling->name);
-		if (ptr->chip->chiph_exists) {
-			fprintf(fil, "\t.chip_ops = &%s_ops,\n", ptr->chip->name_underscore);
-			fprintf(fil, "\t.chip_info = &%s_info_%d,\n", ptr->chip->name_underscore, ptr->chip->id);
-		}
-		if (ptr->nextdev)
-			fprintf(fil, "\t.next=&%s\n", ptr->nextdev->name);
-		fprintf(fil, "};\n");
-	}
-	if ((ptr->type == chip) && (ptr->chiph_exists)) {
-		if (ptr->reg) {
-			fprintf(fil, "struct %s_config %s_info_%d\t= {\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
-			struct reg *r = ptr->reg;
-			while (r) {
-				fprintf(fil, "\t.%s = %s,\n", r->key, r->value);
-				r = r->next;
-			}
-			fprintf(fil, "};\n\n");
-		} else {
-			fprintf(fil, "struct %s_config %s_info_%d;\n", ptr->name_underscore, ptr->name_underscore, ptr->id);
-		}
-	}
-}
-
-void walk_device_tree(FILE *fil, struct device *ptr, void (*func)(FILE *, struct device*), struct device *chips) {
-	do {
-		func(fil, ptr);
-		ptr = ptr->next_sibling;
-	} while (ptr);
-}
-
-struct device mainboard = {
-	.name = "mainboard",
-	.name_underscore = "mainboard",
-	.id = 0,
-	.chip = &mainboard,
-	.type = chip,
-	.chiph_exists = 1,
-	.children = &root
-};
-
-struct device root = {
-	.name = "dev_root",
-	.name_underscore = "dev_root",
-	.id = 0,
-	.chip = &mainboard,
-	.type = device,
-	.path = " .type = DEVICE_PATH_ROOT ",
-	.ops = "&default_dev_ops_root",
-	.parent = &root,
-	.bus = &root,
-	.enabled = 1
-};
-
-int main(int argc, char** argv) {
-	if (argc != 3) {
-		printf("usage: sconfig vendor/mainboard outputdir\n");
-		return 1;
-	}
-	char *mainboard=argv[1];
-	char *outputdir=argv[2];
-	char *devtree=malloc(strlen(mainboard)+30);
-	char *outputc=malloc(strlen(outputdir)+10);
-	sprintf(devtree, "src/mainboard/%s/devicetree.cb", mainboard);
-	sprintf(outputc, "%s/static.c", outputdir);
-
-	headers.next = malloc(sizeof(struct header));
-	headers.next->name = malloc(strlen(mainboard)+12);
-	headers.next->next = 0;
-	sprintf(headers.next->name, "mainboard/%s", mainboard);
-
-	FILE *filec = fopen(devtree, "r");
-	yyrestart(filec);
-
-	FILE *staticc = fopen(outputc, "w");
-
-	cur_bus = cur_parent = lastdev = head = &root;
-	yyparse();
-	fclose(filec);
-
-	if ((head->type == chip) && (!head->chiph_exists)) {
-		struct device *tmp = head;
-		head = &root;
-		while (head->next != tmp) head = head->next;
-	}
-
-	fprintf(staticc, "#include <device/device.h>\n");
-	fprintf(staticc, "#include <device/pci.h>\n");
-	struct header *h = &headers;
-	while (h->next) {
-		h = h->next;
-		fprintf(staticc, "#include \"%s/chip.h\"\n", h->name);
-	}
-	fprintf(staticc, "\n/* pass 0 */\n");
-	walk_device_tree(staticc, &root, pass0, NULL);
-	fprintf(staticc, "\n/* pass 1 */\nstruct mainboard_config mainboard_info_0;\nstruct device **last_dev_p = &%s.next;\n", lastdev->name);
-	walk_device_tree(staticc, &root, pass1, NULL);
-
-	fclose(staticc);
-	return 0;
-}
+void postprocess_devtree(void);
+struct device *new_chip(char *path);
+void add_header(struct device *dev);
+struct device *new_device(const int bus, const char *devnum, int enabled);
+void alias_siblings(struct device *d);
+void add_resource(int type, int index, int base);
+void add_register(char *name, char *val);