/*
 * Copyright (C) 2000-2003 ASANO Masahiro
 */

#include <unistd.h>
#include "crash.h"

PRIVATE addr_t page(), vm_area_struct();
const commandtable_t
	command_page = {"page", page, "address", "print page table"},
	command_vm_area_struct =
	{"vm_area_struct", vm_area_struct, "address", "print vm_area_struct table"};

extern const char head_page[];
extern addr_t print_page();
extern addr_t print_vm_area_struct();
addr_t page_hash_table_addr;
addr_t page_hash_bits_addr;

PRIVATE addr_t
page()
{
	addr_t addr;
	int i, c;
	addr_t page_hash_table;
	unsigned int page_hash_bits;
	int page_hash_size;

	while ((c = getopt(argcnt, args, "")) != EOF) {
		switch (c) {
		default:
			THROW(usage);
		}
	}

	GETADDR(page_hash_table);
	GETADDR(page_hash_bits);

	if (argcnt > optind) {
		mprintf(head_page);
		for (i = optind; i < argcnt; i++) {
			addr = getaddr(args[i]);
			addr = print_page(addr);
		}
	} else {
		mprintf(head_page);
		memread(page_hash_bits_addr, sizeof(page_hash_bits), &page_hash_bits, "page_hash_bits");
		memread(page_hash_table_addr, sizeof(addr_t), &page_hash_table, "page_hash_table");
		page_hash_size = (1 << page_hash_bits);
		for (i = 0; i < page_hash_size; i++) {
			memread(page_hash_table + i * sizeof(addr_t), sizeof(addr_t), &addr, "page_hash_table");
			while (addr) {
				addr = print_page(addr);
			}
		}
		mprintf(head_page);
	}
	return 0;
}

PRIVATE addr_t
vm_area_struct()
{
	int c;

	while ((c = getopt(argcnt, args, "")) != EOF) {
		switch (c) {
		default:
			THROW(usage);
		}
	}

	if (optind == argcnt) {
		THROW(usage);
	}
	while (args[optind]) {
		(void)print_vm_area_struct(getaddr(args[optind]));
		optind++;
	}
	return 0;
}
