/* $Id: lkstbuf.c,v 1.7 2002/06/28 11:27:53 indoh Exp $ */
/* command/lkstbuf.c */

/************************************************************
 *
 * COPYRIGHT (C) HITACHI,LTD. 2002 ALL RIGHTS RESERVED.
 * WRITTEN BY HITACHI SYSTEMS DEVELOPMENT LABORATORY,
 *            HITACHI CENTRAL RESEARCH LABORATORY.
 *
 * Created by K.Hatasaki <keisukeh@crl.hitachi.co.jp>
 *
 ************************************************************/

#include "command.h"

#define NAME	"lkstbuf"
#define VERSION "1.1"

#define NR_CMD  11
#if DEBUG
#define NR_CMD  12
#endif /* DEBUG */

void usage(void);

void call_usage(int *, char **);
void call_version(int*, char**);
void call_list(int*, char**);
void call_create(int*, char**);
void call_del(int*, char**);
void call_read(int*, char**);
void call_shift(int*, char**);

#if DEBUG
void call_seek(int*, char**);
#endif /* DEBUG */

void call_print(int*, char**);
int  nors_analyzer(char*);

int main(int argc, char **argv)
{
	int i;

	struct command cmd[] = 
	{
		[0] = {"help", &call_usage},
		[1] = {"ver", &call_version},
		[2] = {"version", &call_version},
		[3] = {"list", &call_list},
		[4] = {"ls", &call_list},
		[5] = {"create", &call_create},
		[6] = {"delete", &call_del},
		[7] = {"del", &call_del},
		[8] = {"read", &call_read},
		[9] = {"shift", &call_shift},
		[10] = {"print", &call_print},
#if DEBUG
		[11] = {"seek", &call_seek},
#endif /* DEBUG */
	};

	if (argc == 1) { /* no command */
		usage();
	} else {
		for (i = 0; i < NR_CMD; i++) {
			if (!strcmp(cmd[i].name, argv[1])) {
				cmd[i].func(&argc, argv);
				break;
			}
		}
		if (i == NR_CMD)
			badcommand(argv[1]);
	}

	exit(0);
}

void usage(void)
{
	printf("This controls kernel event buffers in LKST.\n");
	printf("Usage:\n\t%s command [option(s)]\n\n", NAME);
	printf("<COMMAND>\n");
	printf("shift\t\tChange currently selected buffer to next buffer.\n");
	printf("\t\t<OPTION>\n");
	printf("\t\t[-c cpu_id]\n");
	printf("create\t\tCreate a new kernel event buffer\n");
	printf("\t\t<OPTION>\n");
	printf("\t\t[-b buffer_id] [-c cpu_id] -s size\n");
	printf("delete/del\tDelete a kernel event buffer.\n");
	printf("\t\t<OPTION>\n");
	printf("\t\t-b buffer_id\n");
	printf("list/ls\t\tOutput a list of all kernel event buffers.\n");
	printf("read\t\tOutput a content of kernel event buffer(s).\n");
	printf("\t\t<OPTION>\n");
	printf("\t\t[-b buffer_id] [-f output_file] [-n number]\n");
	printf("print\t\tOutput a content of kernel event buffer(s) infomation.\n");
	printf("\t\t<OPTION>\n");
	printf("\t\t[-b buffer_id]\n");
	printf("\t\t[-f output_file] [-c cpu_id] [-e 'event_name,!eventname']\n");
	printf("\t\t[-n number] [-r] [-h]\n");
	printf("version/ver\tPrint version information.\n");
	printf("help\t\tPrint this message.\n");
	exit(0);
}

void call_usage(int *argc, char **argv)
{
	usage();
}

void call_version(int *argc, char **argv)
{
	version(NAME, VERSION);
}

void call_list(int *argc, char **argv)
{
	buffer_list();
}

void call_create(int *argc, char **argv)
{
	int c;
	int i;
	int size_set = 0;
	int cpu = -1;
	lkst_buffer_id id = LKST_BUFFER_ID_VOID;
	size_t size;

	while((c = getopt(*argc, argv, "b:c:s:")) != EOF) {
		switch(c) {
		case 'b' :
			id = atoi(optarg);
			break;
		case 'c' :
			cpu = atoi(optarg);
			break;
		case 's' :
			size_set = 1;
			size = atoi(optarg);
			break;
		default :
			usage();
		}
	}

	if (!size_set)
		needopt();

	buffer_create(cpu, id, size);
}

void call_del(int *argc, char **argv)
{
	int c;
	lkst_buffer_id id;

	c = getopt(*argc, argv, "b:");

	switch(c) {
	case 'b' :
		id = atoi(optarg);
		break;
	case -1:
		needopt();
		break;
	default :
		usage();
		break;
	}

	buffer_delete(id);
}

void call_read(int *argc, char **argv)
{
	int c;
	int i;
	int num_set = 0;
	int file_set = 0;
	lkst_buffer_id id = LKST_BUFFER_ID_VOID;
	char file_name[255];
	unsigned int num;

	while((c = getopt(*argc, argv, "b:n:f:")) != EOF) {
		switch(c) {
		case 'b' :
			id = atoi(optarg);
			break;
		case 'n' :
			num_set = 1;
			num = atoi(optarg);
			break;
		case 'f' :
			file_set = 1;
			strncpy(file_name, optarg, 255);
			break;
		default :
			usage();
		}
	}

	if (num_set && id != LKST_BUFFER_ID_VOID && !file_set)
		buffer_read_fast(id, num);
	else 
		buffer_read(id, num, file_name, num_set, file_set);
}

void call_shift(int *argc, char **argv)
{
	int c;
	int cpu;
	int all = 0;

	c = getopt(*argc, argv, "c:");

	switch(c) {
	case 'c' :
		cpu = atoi(optarg);
		break;
	case -1:
		all = 1;
		break;
	default :
		usage();
		break;
	}

	if (all)
		buffer_shift_all();
	else
		buffer_shift(cpu);
}

void call_print(int *argc, char **argv)
{
	int  c;
	int  file_set        = 0;
	int  arg_cpu_id      = -1;
	int  arg_filter_flag = 0;
	int  arg_entry_num   = -1;
	int  arg_sort_flag   = 0;
	int  help_flag       = 0;
	char* program_name;
	char arg_inputfile[255];
	char event_work[255];
	lkst_buffer_id id = LKST_BUFFER_ID_VOID;

	program_name = argv[0];

	while ((c = getopt(*argc, argv, "b:f:c:e:n:rh")) != EOF) {
		switch (c) {
		case 'b' :
			if (nors_analyzer(optarg)) {
				id = atoi(optarg);
			} else {
				usage();
			}
			break;
		case 'f' :
			file_set = 1;
			strncpy(arg_inputfile, optarg, 255);
			break;
		case 'c' :
			if (nors_analyzer(optarg)) {
				arg_cpu_id = atoi(optarg);
			} else {
				usage();
			}
			break;
		case 'e' :
			arg_filter_flag = 1;
			strncpy(event_work, optarg, 255);
			break;
		case 'n' :
			if (nors_analyzer(optarg)) {
				arg_entry_num = atoi(optarg);
			} else {
				usage();
			}
			break;
		case 'r' :
			arg_sort_flag = 1;
			break;
		case 'h' :
			help_flag = 1;
			break;
		default :
			usage();
			break;
		}
	}

	if (help_flag) {
		help_viewer(program_name);
		exit(1);
	}
	if (file_set) {
		buffer_print_wonly(program_name, arg_cpu_id, arg_filter_flag,
				   arg_entry_num, arg_sort_flag, arg_inputfile, event_work);
	} else {
		buffer_print_randw(id, program_name, arg_cpu_id, arg_filter_flag, arg_entry_num, arg_sort_flag, event_work);
	}
}

int nors_analyzer(char* str)
{
	int i;
	for (i=0;i<(signed int)strlen(str);i++) {
		if ( !(( str[i]>='0' )&&( str[i]<='9' )) ) {
			return 0;
		}
	}
	return 1;
}

#if DEBUG
void call_seek(int *argc, char **argv)
{
	int c;
	int i;
	int id_set;
	int offset_set;
	lkst_buffer_id id;
	size_t offset;

	while((c = getopt(*argc, argv, "b:o:")) != EOF) {
		switch(c) {
		case 'b' :
			id_set = 1;
			id = atoi(optarg);
			break;
		case 'o' :
			offset_set = 1;
			offset = atoi(optarg);
			break;
		default :
			usage();
		}
	}

	if (!id_set || !offset_set)
		needopt();

	buffer_seek(id, offset);
}
#endif /* DEBUG */
