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

#include <sys/stat.h>
#include <unistd.h>
#include "crash.h"

PRIVATE addr_t inode(), address_space();
const commandtable_t command_inode =
	{"inode", inode, "[-f] [address]", "print inode table"};
const commandtable_t command_address_space =
	{"address_space", address_space, "[-cdl] address", "print address_space table\n  -c  print clean pages\n  -d  print dirty pages\n  -l  print locked pages"};

addr_t inode_hashtable_addr;
addr_t i_hash_mask_addr;

extern addr_t print_inode();
extern void print_address_space();

PRIVATE addr_t
inode()
{
	int i, c;
	int full = 0;
	addr_t hash_top, addr = 0;
	unsigned int i_hash_mask;
	addr_t inode_hashtable;
	extern void prhead_inode();

	while ((c = getopt(argcnt, args, "f")) != EOF) {
		switch (c) {
		case 'f':
			full = 1;
			break;
		default:
			THROW(usage);
		}
	}

	GETADDR(inode_hashtable);
	GETADDR(i_hash_mask);

	if (argcnt > optind) {
		if (!full) prhead_inode();
		for (i = optind; i < argcnt; i++) {
			addr = getvalue(args[i]);
			if (full) prhead_inode();
			addr = print_inode(addr, full);
		}
	} else {
		memread(i_hash_mask_addr, sizeof(i_hash_mask), &i_hash_mask, "i_hash_mask");
		memread(inode_hashtable_addr, sizeof(hash_top), &hash_top, "inode_hashtable");
		if (!full) prhead_inode();
		for (i = 0; i <= i_hash_mask; i++) {
			memread(hash_top + sizeof(inode_hashtable) * i, sizeof(inode_hashtable), &inode_hashtable, "inode_hashtable");
			for (addr = (addr_t)inode_hashtable; addr; ) {
				if (full) prhead_inode();
				addr = print_inode(addr, full);
			}
		}
	}
	return addr;
}

PRIVATE addr_t
address_space()
{
	addr_t addr;
	int i, c;
	int plist = 0;

	while ((c = getopt(argcnt, args, "cdl")) != EOF) {
		switch (c) {
		case 'c':
			plist |= 1;	break;
		case 'd':
			plist |= 2;	break;
		case 'l':
			plist |= 4;	break;
		default:
			THROW(usage);
		}
	}

	if (optind == argcnt) {
		THROW(usage);
	}
	for (i = optind; i < argcnt; i++) {
		if (i > optind)
			mprintf("\n");
		addr = getvalue(args[i]);
		print_address_space(addr, plist);
	}
	return 0;
}
