/*
 * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
 */
#include <lcrash.h>
#include <string.h>

/* Forward declaration
 */
void module_usage(command_t *);

/* 
 * module_cmd() -- Command for ...
 */
int
module_cmd(command_t *cmd)
{
	void * modptr = NULL;
	kaddr_t modaddr = 0;
	char * modname = NULL;

	if(cmd->nargs==0){
		if(kl_get_module(modname,&modaddr, &modptr)){
			if(KL_ERROR == KLE_NO_MODULE_LIST) {
				fprintf(KL_ERRORFP, "ERROR: ");
				kl_print_error();
				kl_reset_error();
			} else {
				fprintf(KL_ERRORFP, "Error while reading module"
					" structure from dump.\n");
			}
			return(1);
		}
		kl_free_block(modptr);
		if(walk_structs("module", "next", -1, modaddr,
				cmd->flags, cmd->ofp)){
			fprintf(KL_ERRORFP, "Error while walking through "
				"module structures of dump.\n");
			return(1);
		}
	} else if (cmd->nargs ==1) {
		if(kl_get_module(cmd->args[0], &modaddr, &modptr)) {
			if(KL_ERROR == KLE_NO_MODULE_LIST) {
				fprintf(KL_ERRORFP, "ERROR: ");
				kl_print_error();
				kl_reset_error();
			} else {
				fprintf(KL_ERRORFP, "Could not load module "
					"structure from dump for module: %s\n", 
					cmd->args[0]);
			}
			return(1);
		}
		module_banner(cmd->ofp, cmd->flags | BANNER | SMAJOR);
		print_module(modaddr, modptr, cmd->flags, cmd->ofp);
		module_banner(cmd->ofp, cmd->flags |  SMAJOR);
		kl_free_block(modptr);
	} else {
		fprintf(KL_ERRORFP, "Invalid commandline.\n");
		module_usage(cmd);
		return(1);
	}
	return(0);
}

#define _MODULE_USAGE \
"\n        [modulename]"\
"\n        [-f [modulename]]"\
"\n        [-i iteration_threshold]"\
"\n        [-w outfile]"

#define _MODULE_HELP \
"Display list of loaded modules and module symbols.\n"\
"\nOPTIONS:"\
"\n modulename"\
"\n       Display information of (all) module structure(s) in linked list"\
"\n       \"module_list\" of the kernel."\
"\n       Shows address of module structure, and size, usecount, name of"\
"\n       module, and modules that depend on the module."\
"\n       Equals \"cat /proc/modules\" in a running Linux system."\
"\n -f [modulename]"\
"\n       Show list of exported module symbols of (all) module structure(s)"\
"\n       in linked list \"module_list\" of the kernel."\
"\n       Equals \"cat /proc/ksyms\" in a running Linux system."\
"\n -i iteration_threshold"\
"\n       By default certain loops are interrupted after 10'000 iterations"\
"\n       to avoid endless loops while following invalid pointers. Using"\
"\n       this option you can change the threshold for the current command."\
"\n       A value '0' means infinite iteration threshold, i.e. no"\
"\n       interruption of the loop is caused by reaching any threshold.\n"\
"\nThe \"struct module kernel_module\" can be accessed by using "\
"\n\"kernel_module\" as 'modulename'."

/*
 * module_usage() -- Print the usage string for the 'module' command.
 */
void
module_usage(command_t *cmd)
{
	CMD_USAGE(cmd, _MODULE_USAGE);
}


/*
 * module_help() -- Print the help information for the 'module' command.
 */
void
module_help(command_t *cmd)
{
	CMD_HELP(cmd, _MODULE_USAGE, _MODULE_HELP);
}

/*
 * module_parse() -- Parse the command line arguments for 'module'.
 */
int
module_parse(command_t *cmd)
{
	option_t *op;

	if (set_cmd_flags(cmd, (C_FULL|C_WRITE), "i:")) {
		return(1);
	}
	op = cmd->options;

	while (op) {
		switch(op->op_char) {
			case 'i':
				cmd->flags |= C_ITER;
				kl_get_value(op->op_arg, 0, 0, &iter_threshold);
				if(KL_ERROR){
					fprintf(KL_ERRORFP, "Invalid value for "
						"iter_threshold.\n");
					return(1);
				}
				break;
		}
		op = op->op_next;
	}
	return(0);
}

/*
 * module_complete() -- Complete arguments of 'module' command.
 */
char *
module_complete(command_t *cmd)
{
	char *ret;

	/* complete standard options (for example, -w option) arguments
	 */
	if ((ret = complete_standard_options(cmd)) != NOT_COMPLETED) {
		return(ret);
	}
	fprintf(cmd->ofp, "\n");
	module_usage(cmd);
	return(DRAW_NEW_ENTIRE_LINE);
}
