/*
 * libfdt - Flat Device Tree manipulation
 *	Testcase for fdt_path_offset()
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>

#include <fdt.h>
#include <libfdt.h>

#include "tests.h"
#include "testdata.h"

void vcheck_search(void *fdt, const char *propname, const void *propval,
		  int proplen, va_list ap)
{
	int offset = -1, target;

	do {
		target = va_arg(ap, int);
		verbose_printf("Searching (target = %d): %d ->",
			       target, offset);
		offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
						       propval, proplen);
		verbose_printf("%d\n", offset);

		if (offset != target)
			FAIL("fdt_node_offset_by_prop_value() returns %d "
			     "instead of %d", offset, target);
	} while (target >= 0);
}

void check_search(void *fdt, const char *propname, const void *propval,
		  int proplen, ...)
{
	va_list ap;

	va_start(ap, proplen);
	vcheck_search(fdt, propname, propval, proplen, ap);
	va_end(ap);
}

void check_search_str(void *fdt, const char *propname, const char *propval, ...)
{
	va_list ap;

	va_start(ap, propval);
	vcheck_search(fdt, propname, propval, strlen(propval)+1, ap);
	va_end(ap);
}

#define check_search_val(fdt, propname, propval, ...) \
	{ \
		typeof(propval) val = (propval); \
		check_search((fdt), (propname), &val, sizeof(val), \
			     ##__VA_ARGS__); \
	}

int main(int argc, char *argv[])
{
	void *fdt;
	int subnode1_offset, subnode2_offset;
	int subsubnode1_offset, subsubnode2_offset;

	test_init(argc, argv);
	fdt = load_blob_arg(argc, argv);

	subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
	subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
	subsubnode1_offset = fdt_path_offset(fdt, "/subnode@1/subsubnode");
	subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode@0");

	if ((subnode1_offset < 0) || (subnode2_offset < 0)
	    || (subsubnode1_offset < 0) || (subsubnode2_offset < 0))
		FAIL("Can't find required nodes");

	check_search_val(fdt, "prop-int", TEST_VALUE_1, 0, subnode1_offset,
			 subsubnode1_offset, -FDT_ERR_NOTFOUND);

	check_search_val(fdt, "prop-int", TEST_VALUE_2, subnode2_offset,
			 subsubnode2_offset, -FDT_ERR_NOTFOUND);

	check_search_str(fdt, "prop-str", TEST_STRING_1, 0, -FDT_ERR_NOTFOUND);

	check_search_str(fdt, "prop-str", "no such string", -FDT_ERR_NOTFOUND);

	check_search_val(fdt, "prop-int", TEST_VALUE_1+1, -FDT_ERR_NOTFOUND);

	check_search(fdt, "no-such-prop", NULL, 0, -FDT_ERR_NOTFOUND);

	PASS();
}
