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

#include "command.h"
#include "buffer.h"

#include <linux/lkst_private.h>

#define LKST_ETYPE_DEF_DESCRIPTIONS
#include <linux/lkst_events.h>

#define LKST_ETYPE_DEF_DATATABLE
#include <linux/lkst_events.h>

#define UNDEF_STR "undefined"

int lkst_get_status(struct lkst_status_param *sparam)
{
	int retval,fd;
	fd = open_dev();
	retval = ioctl(fd, LKST_IOC_TRC_STATUS, sparam); /* trc_status */
	close(fd);
	return retval;
}

/* display as classical format */
void classical_buffer_list(int cpu)
{
	int retval;
	int fd;
	int i,j,k;
	char prev_id_str[5]={0}, next_id_str[5]={0};

	struct lkst_buffer_listparam lp;
	struct lkst_buffer_listent listent[LKST_BUFFER_TBL_MAX];
	struct lkst_status_param sparam;

	fd = open_dev();

	retval = ioctl(fd, LKST_IOC_TRC_STATUS, &sparam); /* trc_status */
	if (retval<0) {
		fprintf(stderr, "ioctl(LKST_IOC_TRC_STATUS) error: %s\n", strerror(errno));
		exit(1);
	}
	if( cpu != -1 && !((1UL << cpu) & sparam.online_cpu) ) {
		fprintf(stderr, "error : cannot find cpu %d\n",cpu);
	}
	printf(" id\t cpu\tsize\tprev_id\tnext_id\t    readp\t    writep\twrap\n");	
	printf("%3d\t%3d%c%9d\t%3s\t%3s\t%9d\t%9d\t %1d\n",
	       255, 0, ' ', 
	       sparam.static_buffer_size,
	       "NUL", "NUL", 0,
	       sparam.static_buffer_recid % sparam.static_buffer_size,
	       0);


	for_each_online_cpus( j, sparam.online_cpu) {
		if (cpu != -1 && cpu != j) continue;
		lp.cpu = j;
		lp.listent_num = LKST_BUFFER_TBL_MAX;
		lp.listent = listent;
		retval = ioctl(fd, LKST_IOC_BUFFER_LIST, &lp);	/* buffer list */
		if (retval<0) {
			fprintf(stderr, "ioctl(LKST_IOC_BUFFER_LIST) error: %s\n", strerror(errno));
			exit(1);
		}
		if (lp.listent_num < lp.buffer_num) lp.buffer_num = lp.listent_num;
		for (i = 0; i < lp.buffer_num; i++) {
			for (k=0;k<lp.buffer_num && listent[k].next!=listent[i].id;k++);
		  	if (k == lp.buffer_num)
				strncpy (prev_id_str, "NUL", 4);
			else
				snprintf (prev_id_str, 4, "%3d", listent[k].id);
		  	if (lp.listent[i].next == LKST_BUFFER_ID_VOID)
				strncpy (next_id_str, "NUL", 4);
			else
				snprintf (next_id_str, 4, "%3d", lp.listent[i].next);
	  		printf("%3d\t%3d%c%9d\t%3s\t%3s\t%9d\t%9d\t %1d\n",
       			       lp.listent[i].id,
			       lp.cpu,
			       (lp.listent[i].id==lp.write_buf)?'*':' ',
			       lp.listent[i].size,
			       prev_id_str,
			       next_id_str,
			       ((lp.listent[i].id==lp.read_buf)?lp.read_pos:LKST_BUFFER_INIT_POS)*64,
			       (listent[i].baseid - listent[i].write_offset)*LKST_EVENT_RECORD_BYTE,
			       0);
		}
	}
	close(fd);
}

static inline char * itosn(char *str, int i, size_t n)
{
	snprintf(str, n, "%d", i);
	return str;
}

static char * bid2str(char *strbuf, lkst_buffer_id id)
{
	if (id == LKST_BUFFER_ID_VOID) {
		strncpy(strbuf," --", 4);
	}else
		snprintf(strbuf, 4, "%3d",id);
	return strbuf;
}

static int lkst_get_cpu_online_map(int fd) 
{
	int retval;
	struct lkst_status_param param;

	retval = ioctl(fd, LKST_IOC_TRC_STATUS, &param); /* trc_status */
	if (retval<0) {
		fprintf(stderr, "ioctl(LKST_IOC_TRC_STATUS) error: %s\n", strerror(errno));
		exit(1);
	}
	return param.online_cpu;
}

static void lkst_buffer_static_list(FILE *fout, int fd, 
				    struct lkst_status_param *param)
{
	int retval;
	retval = ioctl(fd, LKST_IOC_TRC_STATUS, param); /* trc_status */
	if (retval<0) {
		fprintf(stderr, "ioctl(LKST_IOC_TRC_STATUS) error: %s\n", strerror(errno));
		exit(1);
	}

	fprintf(fout, "Static buffer Size: %9d Recid: %9d\n",
		param->static_buffer_size, param->static_buffer_recid);
}

static int lkst_buffer_list(FILE *fout, int fd, int cpu, int level)
{
	int i;
	char buf[4][8];
	struct lkst_buffer_listparam lp={0};
	struct lkst_buffer_listent listent[LKST_BUFFER_TBL_MAX]={{0}};

	lp.cpu = cpu;
	lp.listent_num = LKST_BUFFER_TBL_MAX;
	lp.listent = listent;

	if ( ioctl(fd, LKST_IOC_BUFFER_LIST, &lp) < 0)
		return -1;

	fprintf(fout,"CPU:%2d  Buffers: %3d  Owner_pid:%5s\n",
		lp.cpu, lp.buffer_num,
		(lp.owner==PID_MAX+1)?"--":itosn(buf[0],lp.owner,6));
	
	if (lp.listent_num < lp.buffer_num) lp.buffer_num = lp.listent_num;
   
	fprintf(fout, "cpu  id   readp  writep    size size[Byte]   recid   R W  next rq_p rq_n \n");
	for (i = 0; i < lp.buffer_num; i++) {
		fprintf(fout," %2d %3d %7s %7d %7d %9d %8x   %c %c   %3s %4s %4s\n",
			lp.cpu,
			listent[i].id,
			(listent[i].id==lp.read_buf)?
				itosn(buf[3],lp.read_pos,8):"--",
			listent[i].baseid - listent[i].write_offset,
			listent[i].size/LKST_EVENT_RECORD_BYTE,
			listent[i].size,
			LKST_BUFFER_RECID(listent[i].id, listent[i].baseid),
			(listent[i].id==lp.read_buf)?'<':'-',
			(listent[i].id==lp.write_buf)?'>':'-',
			bid2str(buf[0],listent[i].next),
			(listent[i].id==lp.rq_head)?
				"head":bid2str(buf[1],listent[i].rq_prev),
			(listent[i].id==lp.rq_tail)?
				"tail":bid2str(buf[2],listent[i].rq_next));
	}
	return 0;
}


void buffer_list(int cpu_id, int level)
{
	int cpu;
	int fd;
	struct lkst_status_param param={0};
	fd = open_dev();
	if(fd <0) {
		fprintf(stderr,"open() error: %s\n", strerror(errno));
		exit(1);
	}
	if(cpu_id == -1) {
		lkst_buffer_static_list(stdout,fd,&param);
	}
	for(cpu = 0;cpu<LKST_CPU_MAX;cpu++) {
		if( cpu != cpu_id ){
			if (cpu_id != -1 || 
			    !(param.online_cpu & (1UL<<cpu))) continue;
		}
		
		if ( lkst_buffer_list(stdout, fd, cpu, level) < 0) {
			fprintf(stderr, "ioctl(LKST_IOC_BUFFER_LIST) error: %s\n", strerror(errno));
			continue;
		}
	}
	close(fd);
}

void buffer_link(int cpu, lkst_buffer_id id,lkst_buffer_id next)
{
	struct lkst_buffer_linkparam param;
	int fd,retval;

	fd = open_dev();

	if ( cpu != -1 ) {
		param.cpu = cpu;		
		param.id = id ;
		param.next = next;
		retval = ioctl(fd, LKST_IOC_BUFFER_LINK, &param);
		if (retval < 0) {
			fprintf(stderr, "ioctl(LKST_IOC_BUFFER_LINK) error: %s\n", strerror(errno));
			exit(1);
		} else {
			if (next != LKST_BUFFER_ID_VOID) {
				printf("Buffer ID %d is linked to ID %d on CPU %d\n", id, next, cpu);
			}else { 
				printf("Link from buffer ID %d is disconnected on CPU %d\n", id, cpu);
			}
		}
	}else {
		int online;
		online = lkst_get_cpu_online_map(fd);
		for_each_online_cpus(cpu, online) {
			param.cpu = cpu;		
			param.id = id ;
			param.next = next;
			retval = ioctl(fd, LKST_IOC_BUFFER_LINK, &param);
			if (retval < 0) {
				fprintf(stderr, "ioctl(LKST_IOC_BUFFER_LINK) error: %s\n", strerror(errno));
			} else {
				if (next != LKST_BUFFER_ID_VOID) {
					printf("Buffer ID %d is linked to ID %d on CPU %d\n", id, next, cpu);
				}else { 
					printf("Link from buffer ID %d is disconnected on CPU %d\n", id, cpu);
				}
			}
		}
	}
	
	close(fd);
}

void buffer_create(int cpu, lkst_buffer_id id, 
		   size_t size, lkst_buffer_id nxid)
{
	int retval;
	int fd;
	struct lkst_buffer_param param;

	fd = open_dev();
	
	if ( cpu != -1 ) {
		param.cpu = cpu;
		param.id = id;
		param.size = size;
		param.next = nxid;

		retval = ioctl(fd, LKST_IOC_BUFFER_CREATE, &param); /* buffer_create */
		
		if (retval < 0) {
			fprintf(stderr, "ioctl(LKST_IOC_BUFFER_CREATE) error: %s\n", strerror(errno));
			exit(1);
		}
		printf("New buffer was created, cpu=%d, id=%d size=%ld + %ld(margin)\n",
		       param.cpu, param.id, param.result_size-LKST_BUFFER_MARGIN_BYTE,
		       LKST_BUFFER_MARGIN_BYTE );
	}else {
		int online;
		online = lkst_get_cpu_online_map(fd);
		for_each_online_cpus(cpu, online) {
			param.cpu = cpu;
			param.id = id;
			param.size = size;
			param.next = nxid;
			
			retval = ioctl(fd, LKST_IOC_BUFFER_CREATE, &param); /* buffer_create */
			
			if (retval < 0) {
				fprintf(stderr, "ioctl(LKST_IOC_BUFFER_CREATE) error: %s\n", strerror(errno));
				fprintf(stderr, "Failed to create a buffer on CPU %d\n",cpu);
			}else
				printf("New buffer was created, cpu=%d, id=%d size=%ld + %ld(margin)\n",
				       param.cpu, param.id, param.result_size-LKST_BUFFER_MARGIN_BYTE,
				       LKST_BUFFER_MARGIN_BYTE );
		}
	}
	close(fd);
}


void buffer_delete(int cpu, lkst_buffer_id id)
{
	int retval;
	int fd;
	struct lkst_buffer_delparam param;

	fd = open_dev();

	if ( cpu != -1 ) {
		param.cpu = cpu;
		param.id = id;
		retval = ioctl(fd, LKST_IOC_BUFFER_DELETE, &param);	/* buffer_delete */
		
		if (retval < 0) {
			fprintf(stderr, "ioctl(LKST_IOC_BUFFER_DELETE) error: %s\n", strerror(errno));
			exit(1);
		}
		printf("Buffer id=%d was deleted.\n", id);
	}else{
		int online;
		online = lkst_get_cpu_online_map(fd);
		for_each_online_cpus(cpu, online) {
			param.cpu = cpu;
			param.id = id;
			retval = ioctl(fd, LKST_IOC_BUFFER_DELETE, &param);	/* buffer_delete */
			
			if (retval < 0) {
				fprintf(stderr, "ioctl(LKST_IOC_BUFFER_DELETE) error: %s\n", strerror(errno));
				fprintf(stderr, "Failed to delete a buffer on CPU %d\n",cpu);
			}else
				printf("Buffer id=%d was deleted.\n", id);
		}
	}
	close(fd);
}

int lkst_buffer_jump(int fd, int cpu, lkst_buffer_id dest)
{
	struct lkst_buffer_jumpparam param;
	param.cpu = cpu;
	param.dest = dest;
	return ioctl(fd, LKST_IOC_BUFFER_JUMP, &param);
}

int lkst_buffer_shift(int fd, int cpu)
{
	return ioctl(fd, LKST_IOC_BUFFER_SHIFT, cpu);
}

void buffer_shift(int cpu)
{
	int fd;
	int retval;

	fd = open_dev();

	if ( cpu != -1 ) {
		retval = lkst_buffer_shift(fd, cpu);	/* buffer_shift */
		if (retval < 0) {
			fprintf(stderr, "lkst_buffer_shift() error: %s\n", strerror(errno));
			exit(1);
		}
		printf("Currently selected buffer changed on CPU %d\n", cpu);
	}else {
		int online;
		online = lkst_get_cpu_online_map(fd);
		for_each_online_cpus(cpu, online) {
			retval = lkst_buffer_shift(fd, cpu);	/* buffer_shift */
			if (retval < 0) {
				fprintf(stderr, "lkst_buffer_shift() error: %s\n", strerror(errno));
				fprintf(stderr, "Failed to change current buffer on CPU %d\n",cpu);
			}else
				printf("Currently selected buffer changed on CPU %d\n", cpu);
		}
	}

	close(fd);
}

void buffer_jump(int cpu, lkst_buffer_id dest)
{
	int fd;
	int retval;

	fd = open_dev();

	if ( cpu != -1 ) {
		retval = lkst_buffer_jump(fd, cpu, dest);	/* buffer_shift */
		if (retval < 0) {
			fprintf(stderr, "lkst_buffer_jump() error: %s\n", strerror(errno));
			exit(1);
		}
		printf("Currently selected buffer changed to %d on CPU %d\n", dest, cpu);
	} else {
		int online;
		online = lkst_get_cpu_online_map(fd);
		for_each_online_cpus(cpu, online) {
			retval = lkst_buffer_jump(fd, cpu, dest);	/* buffer_shift */
			if (retval < 0) {
				fprintf(stderr, "lkst_buffer_jump() error: %s\n", strerror(errno));
				fprintf(stderr, "Failed to change current buffer on CPU %d\n",cpu);
			}else
				printf("Currently selected buffer changed to %d on CPU %d\n", dest, cpu);
		}
	}
	close(fd);
}


int lkst_set_rmod(int fd, int cpu, struct lkst_log_buffer *lbuffer)
{
	struct lkst_buffer_srmodparam param;
	int ret;
	param.cpu = cpu;
	param.mode = STD;
	ret = ioctl(fd, LKST_IOC_BUFFER_SETRMOD, &param);
	if( ret >= 0) {
		lbuffer->xtime = param.xtime;
		lbuffer->tsc = param.tsc;
		lbuffer->cpu_freq = param.cpu_freq;
		lbuffer->endian_big = param.endian_big;
		lbuffer->buf_ver = param.buf_ver;
		strncpy(lbuffer->arch, param.arch,4);
	}
	return ret;
}

int lkst_buffer_read(int fd, struct lkst_log_buffer *lbuffer)
{
	return ioctl(fd, LKST_IOC_BUFFER_READ, lbuffer);
}

void buffer_write_to_file(int fd_o,
			  struct lkst_log_buffer *lbuffer)
{
	int j;
	u_int64_t cpu_hz; 
	struct timespec *buf;
	struct timespec base, diff;
	lkst_tsc_t base_cnt, log_cnt, diff_cnt;
	static int write_once_flag = 0;

	/* write log header and info-record */
	if(!write_once_flag){
		log_header_t logh = {
			log_magic: LOGFILE_MAGIC,
			log_version: 0
		};
		struct posix_log_entry posix_entry = {
			log_size: 2*sizeof(int) + sizeof(char)*LKST_ARCH_NAME_LEN,
			log_format:PXLOG_BINARY
		};
		write_once_flag=1;
		write(fd_o, &logh, sizeof(log_header_t));
		write(fd_o, &posix_entry, sizeof(struct posix_log_entry));
		write(fd_o, &(lbuffer->endian_big), sizeof(int));
		write(fd_o, &(lbuffer->buf_ver), sizeof(int));
		write(fd_o, lbuffer->arch, sizeof(char)*LKST_ARCH_NAME_LEN);
	}

	/* convert mc to time */

	base_cnt = lbuffer->tsc;
	base.tv_sec = lbuffer->xtime.tv_sec;
	base.tv_nsec = 1000*lbuffer->xtime.tv_usec;
	cpu_hz = lbuffer->cpu_freq * 1000; /* convert kHz to Hz */

	for (j = 0; j < (lbuffer->result_read_size / sizeof(struct lkst_log_record)); j++)
	{
				/* buffer[j].posix.log_time.tv_sec has upper 32bit of cpu counter
				   buffer[j].posix.log_time.tv_nsec has lower 32bit of cpu counter */

		buf = &(lbuffer->buffer[j].posix.log_time);

		log_cnt = ((u_int64_t) buf->tv_sec << 32) | (unsigned long) buf->tv_nsec;
		
		if (base_cnt > log_cnt){
			diff_cnt = base_cnt - log_cnt;
			diff.tv_sec  = (unsigned long) (diff_cnt / cpu_hz);
			diff.tv_nsec = (unsigned long) ((diff_cnt % cpu_hz) * 1000000000 / cpu_hz);
			
			if (base.tv_nsec > diff.tv_nsec){
				buf->tv_sec  = base.tv_sec - diff.tv_sec;
				buf->tv_nsec = base.tv_nsec - diff.tv_nsec;
			} else {
				buf->tv_sec  = base.tv_sec - diff.tv_sec - 1;
				buf->tv_nsec = base.tv_nsec + 1000000000 - diff.tv_nsec;
			}
		}
		else{
			diff_cnt = log_cnt - base_cnt;
			diff.tv_sec  = (unsigned long) (diff_cnt / cpu_hz);
			diff.tv_nsec = (unsigned long) ((diff_cnt % cpu_hz) * 1000000000 / cpu_hz);
			
			if(base.tv_nsec + diff.tv_nsec >= 1000000000){
				buf->tv_sec  = base.tv_sec + diff.tv_sec + 1;
				buf->tv_nsec = base.tv_nsec + diff.tv_nsec - 1000000000;
			}
			else{
				buf->tv_sec  = base.tv_sec + diff.tv_sec;
				buf->tv_nsec = base.tv_nsec + diff.tv_nsec;
			}
		}
	}

	/* write to file */
	write(fd_o, lbuffer->buffer, lbuffer->result_read_size);
}

void buffer_display(struct lkst_log_buffer *lbuffer)
{	
	int i, read_count;
	struct lkst_log_record *buffer;
	unsigned int *pArgs;
	int	event_type;
	char	*event_type_name;
	unsigned long long time_cur;

	buffer = lbuffer->buffer;

	read_count =
	    lbuffer->result_read_size / sizeof(struct lkst_log_record);

	printf("result_read_size=%d, num_of_read_entry=%d\n",
	       lbuffer->result_read_size, read_count);

	printf("time: %09ld [sec], %09ld [usec], %018llu [mc]; cpu_freq: %09ld [kHz]\n\n",
	       lbuffer->xtime.tv_sec, lbuffer->xtime.tv_usec, lbuffer->tsc, lbuffer->cpu_freq);

	for (i = 0; i < read_count; i++) {
	  	event_type = (unsigned int) buffer[i].posix.log_event_type;
		event_type_name = lkst_event_type_descriptions[event_type];
		time_cur = ((u_int64_t) buffer[i].posix.log_time.tv_sec << 32) + (unsigned long) (buffer[i].posix.log_time.tv_nsec);


		printf("0x%08x: %016llu [mc], \\\n"
		       " type: %25s(0x%04x), pid: %010u, cpu: %03u \\\n",
		       buffer[i].posix.log_recid,
		       time_cur,
		       event_type_name, event_type,
		       buffer[i].posix.log_pid,
		       buffer[i].posix.log_processor);

		pArgs = (unsigned int *) &buffer[i].log_arg1;

		printf("  0x%08x 0x%08x 0x%08x 0x%08x \\\n"
		       "  0x%08x 0x%08x 0x%08x 0x%08x \\\n\n",
		       pArgs[0], pArgs[1], pArgs[2], pArgs[3], 
		       pArgs[4], pArgs[5], pArgs[6], pArgs[7]);
	}
}

void buffer_read_all(int cpu, unsigned int num, int fout)
{
	int fd;
	int flags;
	struct lkst_log_buffer lbuffer;
	struct lkst_log_record *buffer;

	/*set log buffer*/
	lbuffer.id = LKST_BUFFER_ID_VOID;
	lbuffer.cpu = cpu;
	if ( num != 0 ) 
		lbuffer.read_size = sizeof(struct lkst_log_record) * num;
	else 
		lbuffer.read_size = sizeof(struct lkst_log_record) * 4096;
	if (NULL == (buffer = (struct lkst_log_record *)malloc(lbuffer.read_size))) {
		perror("malloc");
		exit(1);
	}
	lbuffer.buffer = buffer;

	/*device read*/
	fd = open_dev();
	flags = fcntl(fd, F_GETFL);
	fcntl(fd, F_SETFL, flags|O_NONBLOCK);

	if ( lkst_set_rmod(fd, cpu, &lbuffer) < 0){
		fprintf(stderr, "lkst_set_rmod() error: %s\n", strerror(errno));
		exit(1);
	}
	/*read loop*/
	do {
		if ( 0> (lbuffer.result_read_size = read(fd, lbuffer.buffer,
							 lbuffer.read_size)) ){
			fprintf(stderr, "read() error: %s\n", strerror(errno));
			break;
		}
		if(fout <= 0)
			buffer_display(&lbuffer);
		else
			buffer_write_to_file(fout, &lbuffer);
	} while(num == 0 && lbuffer.read_size == lbuffer.result_read_size);
	
	free(buffer);

	close(fd);

}

void buffer_read(int cpu, lkst_buffer_id id, unsigned int num, int fout)
{
	int i;
	int fd;
	struct lkst_log_buffer lbuffer;
	struct lkst_log_record *buffer;

	fd = open_dev();

	/*set log buffer */
	lbuffer.id = id;
	lbuffer.cpu = cpu;
	if (id == LKST_BUFFER_ID_VOID ) {
		lbuffer.read_size = LKST_STATIC_BUFFER_COUNT*sizeof(struct lkst_log_record);
	} else if (num != 0){
		lbuffer.read_size = sizeof(struct lkst_log_record) * num;
	} else {
		struct lkst_buffer_listparam lp;
		struct lkst_buffer_listent listent[LKST_BUFFER_TBL_MAX]={{0}};
		lp.cpu = cpu;
		lp.listent_num = LKST_BUFFER_TBL_MAX;
		lp.listent = listent;
		if ( ioctl(fd, LKST_IOC_BUFFER_LIST, &lp) < 0){
			fprintf(stderr, "lkst_buffer_list() error: %s\n", strerror(errno));
			exit(1);
		}
		if(lp.listent_num < lp.buffer_num) lp.buffer_num = lp.listent_num;
		for(i=0;i<lp.buffer_num && listent[i].id != id; i++);
		if(i == lp.buffer_num) {
			fprintf(stderr, "specified buffer not found: id = %d\n", id);
			exit(1);
		}
		lbuffer.read_size = sizeof(struct lkst_log_record) * 
			(listent[i].size/sizeof(struct lkst_event_record));
	}
	if (NULL == (buffer = (struct lkst_log_record *)malloc(lbuffer.read_size))) {
		perror("malloc");
		exit(1);
	}
	lbuffer.buffer = buffer;

	/*device read*/
	lkst_buffer_read(fd, &lbuffer);
	if(fout <= 0)
		buffer_display(&lbuffer);
	else
		buffer_write_to_file(fout, &lbuffer);

	free(buffer);

	close(fd);
}


static int command_analyze(struct lkst_arg_command_analyze *pointcom);
static int buffer_save(struct lkst_arg_buffer_save *pointbuf);
static int get_filedata(struct lkst_arg_get_filedata *pointget);
static int make_pointerarray(struct lkst_arg_make_pointerarray *pointarr);
static int sort_data(struct lkst_arg_sort_data *pointsor);
static int print_data(struct lkst_arg_print_data *pointpri,int arg_csv_flag);
void help_viewer(char* program_name);

//TODO : rewrite me!
void buffer_print_wonly(char*  program_name,    /* name of Execution file */
			int   arg_cpu_id,
			int   arg_filter_flag, /* 1=(-e option published) or 0=(not) */
			int   arg_entry_num,
			int   arg_sort_flag,
			int   arg_csv_flag,
			char* arg_inputfile,   /* name of reading file */
			char* event_work,      /* The argument of "-e" option */
			int   verbose)
{
	FILE                             *fp;
	int                              return_num;   /* return number of function */
	struct lkst_arg_command_analyze  pointcom;
	struct lkst_arg_get_filedata     pointget;
	struct lkst_arg_sort_data        pointsor;
	struct lkst_arg_print_data       pointpri;
	struct lkst_log_record           **evr;
	unsigned long                    *fdata;

	if (verbose) { 
		int i,j;
		for (i=0;i<LKST_ETYPE_MAX;i++) {
			for ( j= 0; j< 4;j++) {
				if (( LKST_event_data[i].LKST_inf_args[j] == 0x00) ||
				    (strcmp( LKST_event_data[i].LKST_inf_args[j], "") == 0)) {
					LKST_event_data[i].LKST_inf_args[j] = UNDEF_STR;
				}
			}
		}
	}
	
	/* judgment of the inputted file name */
	fp = fopen(arg_inputfile, LKST_LOG_FMT_FILE_OPEM_MODE);
	if (fp==NULL) {
		printf("%s: invalid filename %s\n\n", program_name, arg_inputfile);
		exit(1);
	}
	fclose(fp);

	/* analyze argument */
	pointcom.program_name    = program_name;
	pointcom.arg_filter_flag = arg_filter_flag;
	strncpy(pointcom.event_work, event_work, 255);
	/* call function */
	return_num = command_analyze(&(pointcom));
	if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
		printf("%s: error in function-command_analyze\n\n", program_name);
		exit(1);
	}

	/* get filedata */
	pointget.program_name  = program_name;
	pointget.arg_entry_num = arg_entry_num;
	pointget.arg_inputfile = arg_inputfile;
	/* call function */
	return_num = get_filedata(&(pointget));
	if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
		printf("%s: error in function-get_filedata\n\n", program_name);
		exit(1);
	}

	evr   = pointget.evr;
	fdata = pointget.fdata;

	/* sort data */
	pointsor.arg_sort_flag  = arg_sort_flag;
	pointsor.read_entry_num = pointget.read_entry_num;
	pointsor.fdata          = pointget.fdata;
	pointsor.evr            = pointget.evr;
	/* call function */
	return_num = sort_data(&(pointsor));
	if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
		printf("%s: error in function-sort_data\n\n", program_name);
		exit(1);
	}

	/* print data */
	pointpri.arg_entry_num   = pointget.arg_entry_num;
	pointpri.arg_cpu_id      = arg_cpu_id;
	pointpri.arg_filter_flag = arg_filter_flag;
	pointpri.fdata           = pointsor.fdata;
	pointpri.evr             = pointsor.evr;
	/* call function */
	return_num = print_data(&(pointpri),arg_csv_flag);
	if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
		printf("%s: error in function-print_data\n\n", program_name);
		exit(1);
	}

	/* free memory */
	free(evr);
	free(fdata);
	exit(0);
}

void buffer_print_randw(lkst_buffer_id  id, 
			char*          program_name,
			int            arg_cpu_id,
			int            arg_filter_flag,
			int	       arg_csv_flag,
			int            arg_entry_num,
			int            arg_sort_flag,
			char           event_work[])
{
	int                               return_num;
	struct lkst_arg_command_analyze   pointcom;
	struct lkst_arg_buffer_save       pointbuf;
	struct lkst_arg_make_pointerarray pointarr;
	struct lkst_arg_sort_data         pointsor;
	struct lkst_arg_print_data        pointpri;
	struct lkst_log_record            **evr;
	unsigned long                     *fdata;

	if (arg_filter_flag) {
		/* analyze argument */
		pointcom.program_name    = program_name;
		pointcom.arg_filter_flag = arg_filter_flag;
		strncpy(pointcom.event_work, event_work, 255);
		/* call function */
		return_num = command_analyze(&(pointcom));
		if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
			fprintf(stderr,"%s: error in function-command_analyze(%d)\n\n", program_name, return_num);
			exit(1);
		}
	}

	/* get buffer data */
	pointbuf.id      = id;
	pointbuf.cpu	 = arg_cpu_id;
	/* call function */
	return_num = buffer_save(&(pointbuf));
	if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
		fprintf(stderr,"%s: error in function-buffer_save\n\n", program_name);
		exit(1);
	}

	fdata = (unsigned long *)pointbuf.startpoint;

	/* make structpointer array */
	pointarr.program_name   = program_name;
	pointarr.arg_entry_num  = arg_entry_num;
	pointarr.fdata          = fdata;
	pointarr.malloc_size    = pointbuf.malloc_size;
	/* call function */
	return_num = make_pointerarray(&(pointarr));
	if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
		fprintf(stderr,"%s: error in function-make_pointerarray\n\n", program_name);
		exit(1);
	}

	evr   = pointarr.evr;

	/* sort data */
	pointsor.arg_sort_flag  = arg_sort_flag;
	pointsor.read_entry_num = pointarr.read_entry_num;
	pointsor.fdata          = pointarr.fdata;
	pointsor.evr            = pointarr.evr;
	/* call function */
	return_num = sort_data(&(pointsor));
	if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
		fprintf(stderr,"%s: error in function-sort_data\n\n", program_name);
		exit(1);
	}

	/* print data */
	pointpri.arg_entry_num   = pointarr.arg_entry_num;
	pointpri.arg_cpu_id      = arg_cpu_id;
	pointpri.arg_filter_flag = arg_filter_flag;
	pointpri.fdata           = pointsor.fdata;
	pointpri.evr             = pointsor.evr;
	/* call function */
	return_num = print_data(&(pointpri),arg_csv_flag);
	if (return_num < LKST_LOG_FMT_RET_CODE_TRUE) {
		fprintf(stderr,"%s: error in function-print_data\n\n", program_name);
		exit(1);
	}

	/* free memory */
	free(evr);
	free(fdata);
	exit(0);
}

static int command_analyze(struct lkst_arg_command_analyze *pointcom)
{
	int   j;                              /* roop flag                   */
	int   eventnstrlen;                      /* length of string"tmp_Arg"   */
	int   ecom_End;
	int   set;                               /* roop flag                   */
	char  tmp_Arg[LKST_LOG_FMT_SORT_BUF_SIZE];    /* array of event name         */
	int   tmp_Filter_flag;                   /* output or not               */
	char* program_name;                      /* name of Execution file      */
	int   arg_filter_flag;                   /* The argument of "-e" option */
	char  event_work[255];                   /* work array */

	/* get argument */
	program_name    = pointcom->program_name;
	arg_filter_flag = pointcom->arg_filter_flag;
	strncpy(event_work, pointcom->event_work, 255);

	if (arg_filter_flag) {
		ecom_End=1;
		eventnstrlen=0;
		while (ecom_End) {

			set=0;
			while (1) {
				if (strncmp(&event_work[eventnstrlen], ",", 1)==0) {
					/* when "-e xxx,,xxx" or "-e xxx," is specified */
					if ((strncmp(&event_work[eventnstrlen+1], ",", 1)==0) || 
					    (strncmp(&event_work[eventnstrlen+1], "\0", 1)==0)) {
						printf("%s: invalid argument %s\n\n", program_name, event_work);
						return LKST_LOG_FMT_RET_CODE_FALSE;
					}
					strncpy(&tmp_Arg[set], "\0", 1);
					eventnstrlen++;
					break;
				} else if (eventnstrlen==(signed int)strlen(event_work)-1){
					strncpy(&tmp_Arg[set], &event_work[eventnstrlen], 1);
					strncpy(&tmp_Arg[set+1], "\0", 1);
					ecom_End=0;
					break;
				} else {
					strncpy(&tmp_Arg[set], &event_work[eventnstrlen], 1);
				}
				eventnstrlen++;
				set++;
			}

			if (strncmp(&tmp_Arg[0], "!", 1)==0) {            /* if head character is "!" */
				tmp_Filter_flag=0;

				for (j=1; j<(signed int)strlen(tmp_Arg); j++) {
					strncpy(&tmp_Arg[j-1], &tmp_Arg[j], 1);
				}
				strncpy(&tmp_Arg[j-1], "\0", 1);
			} else {
				tmp_Filter_flag=1;
			}

			if (strcmp( tmp_Arg, "all")==0) {                 /* "all" is specified */
				for (j=LKST_EDATA_ID_MIN; j<=LKST_EDATA_ID_MAX; j++) {
					if (LKST_event_data[j].LKST_event_name != NULL) {
						LKST_event_data[j].LKST_filter=tmp_Filter_flag;
					}
				}
				continue;
			}

			/* if the eventname which head character is "!" and specified final */
			if ((tmp_Filter_flag==0) && (ecom_End==0)) {
				for (j=LKST_EDATA_ID_MIN; j<=LKST_EDATA_ID_MAX; j++) {
					if (LKST_event_data[j].LKST_event_name != NULL) {
						LKST_event_data[j].LKST_filter=1;
						if (strcmp( LKST_event_data[j].LKST_event_name, tmp_Arg )==0) {
							LKST_event_data[j].LKST_filter=tmp_Filter_flag;
						}
					}
				}
				continue;
			}

			/* find event name */
			for (j=LKST_EDATA_ID_MIN; j<=LKST_EDATA_ID_MAX; j++) {
				if (LKST_event_data[j].LKST_event_name != NULL) {
					if (strcmp( LKST_event_data[j].LKST_event_name, tmp_Arg )==0) {
						LKST_event_data[j].LKST_filter=tmp_Filter_flag;
						break;
					}
				}
			}

			if (j>LKST_EDATA_ID_MAX) {
				/* can't find event name */
				printf("%s: unknown event name: %s\n\n", program_name, tmp_Arg);
				return LKST_LOG_FMT_RET_CODE_FALSE;
			}
		}
	}
	return LKST_LOG_FMT_RET_CODE_TRUE;
}

static int buffer_save(struct lkst_arg_buffer_save *pointbuf)
{
	lkst_buffer_id               id;
	int                          retval;
	int                          fd;
	int                          i, i_max = 1;
	int                          cnt = 0;
	struct lkst_log_buffer       lbuffer;
	struct lkst_buffer_listparam lp;
	struct lkst_buffer_listent   listent[LKST_BUFFER_TBL_MAX];
	int                          malloc_size;
	struct lkst_log_record       *startpoint;
	char                         *buffoffset;

	log_header_t logh = {
		log_magic: LOGFILE_MAGIC,
		log_version: 0
	};

	int             j;
	u_int64_t       cpu_hz; 
	struct timespec *buf;
	struct timespec base, diff;
	lkst_tsc_t      base_cnt, log_cnt, diff_cnt;

	/* get argument */
	id = pointbuf->id;

	fd = open_dev();

	/* buffer list */
	lp.cpu = pointbuf->cpu;
	lp.listent_num = LKST_BUFFER_TBL_MAX;
	lp.listent = listent;

	if ((retval = ioctl(fd, LKST_IOC_BUFFER_LIST, &lp) < 0)) {
		fprintf(stderr, "ioctl(LKST_IOC_BUFFER_LIST) error: %s\n", strerror(errno));
		perror("buffer_list");
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}
	if (id == LKST_BUFFER_ID_VOID) {
		i_max = LKST_BUFFER_ID_MAX;
	}

	/* measure size of a buffer */
	for (i = 1; i < i_max; i++) {

		if (i_max == 1) {
			lbuffer.id = id;
		} else {
			lbuffer.id = lp.listent[i].id;

			if (lbuffer.id == LKST_BUFFER_ID_VOID) {
				continue;
			}
			if (id != LKST_BUFFER_ID_VOID && lbuffer.id != id) {
				continue;
			}
		}

		/* read and write log buffer */
		lbuffer.read_size = (lp.listent[i].size * sizeof(struct lkst_log_record) /
								LKST_SIZEOF_LKST_EVENT_RECORD);

		cnt++;
		malloc_size += lbuffer.read_size;
	}
	if (cnt == 0 && id != LKST_BUFFER_ID_VOID) {
		printf("Error: Specified buffer id=%d does not exist!\n", id);
	}

	malloc_size += sizeof(log_header_t);

	/* malloc */
	startpoint = (struct lkst_log_record *)malloc(malloc_size);
	if (startpoint==NULL) {
		perror("malloc");
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}
	buffoffset = (char *)startpoint + sizeof(log_header_t);

	/* write log header */
	memcpy((void *)buffoffset-sizeof(log_header_t), (const void *)&logh, sizeof(log_header_t));

	/* write data in memory */
	for (i = 0; i < i_max; i++) {

		if (i_max == 1) {
			lbuffer.id = id;
		} else {
			lbuffer.id = lp.listent[i].id;

			if (lbuffer.id == LKST_BUFFER_ID_VOID) {
				continue;
			}
			if (id != LKST_BUFFER_ID_VOID && lbuffer.id != id) {
				continue;
			}
		}

		lbuffer.buffer = (struct lkst_log_record *)buffoffset;

		retval = ioctl(fd, LKST_IOC_BUFFER_READ, &lbuffer);
		/* buffer read */
		printf("ioctl read buffer id=%d\n", lbuffer.id);
		printf("ioctl retval=%d result_read_size=%d\n", retval,
			lbuffer.result_read_size);

		if (retval < 0) {
			fprintf(stderr, "ioctl(LKST_IOC_BUFFER_READ) error: %s\n", strerror(errno));
			printf("Skip reading this buffer!\n");
			continue;
		}

		/* convert mc to time */

		base_cnt = lbuffer.tsc;
		base.tv_sec = lbuffer.xtime.tv_sec;
		base.tv_nsec = 1000*lbuffer.xtime.tv_usec;
		cpu_hz = lbuffer.cpu_freq * 1000; /* convert kHz to Hz */

		for (j = 0; j < (lbuffer.result_read_size / sizeof(struct lkst_log_record)); j++) {

		/* buffer[j].posix.log_time.tv_sec has upper 32bit of cpu counter
		   buffer[j].posix.log_time.tv_nsec has lower 32bit of cpu counter */

			buf = &(lbuffer.buffer[j].posix.log_time);

			log_cnt = ((u_int64_t) buf->tv_sec << 32) | (unsigned long) buf->tv_nsec;

			if (base_cnt > log_cnt) {
				diff_cnt = base_cnt - log_cnt;
				diff.tv_sec  = (unsigned long) (diff_cnt / cpu_hz);
				diff.tv_nsec = (unsigned long) ((diff_cnt % cpu_hz) * 1000000000 / cpu_hz);

				if (base.tv_nsec > diff.tv_nsec) {
					buf->tv_sec  = base.tv_sec - diff.tv_sec;
					buf->tv_nsec = base.tv_nsec - diff.tv_nsec;
				} else {
					buf->tv_sec  = base.tv_sec - diff.tv_sec - 1;
					buf->tv_nsec = base.tv_nsec + 1000000000 - diff.tv_nsec;
				}
			} else {
				diff_cnt = log_cnt - base_cnt;
				diff.tv_sec  = (unsigned long) (diff_cnt / cpu_hz);
				diff.tv_nsec = (unsigned long) ((diff_cnt % cpu_hz) * 1000000000 / cpu_hz);

				if(base.tv_nsec + diff.tv_nsec >= 1000000000){
					buf->tv_sec  = base.tv_sec + diff.tv_sec + 1;
					buf->tv_nsec = base.tv_nsec + diff.tv_nsec - 1000000000;
				} else {
					buf->tv_sec  = base.tv_sec + diff.tv_sec;
					buf->tv_nsec = base.tv_nsec + diff.tv_nsec;
				}
			}
		}
		/* write to file */
		buffoffset = buffoffset + lbuffer.result_read_size;
	}
	close(fd);

	/* return argument */
	pointbuf->startpoint  = startpoint;
	pointbuf->malloc_size = malloc_size;

	return LKST_LOG_FMT_RET_CODE_TRUE;
}

static int get_filedata(struct lkst_arg_get_filedata *pointget)
{
	FILE                   *fp;                  /* file pointer of reading file */
	struct stat            info;                 /* size of reading file */
	void		       *fdata;
	struct lkst_log_record **evr;                /* array of struct pointer */
	char		       *offset;              /* pointer for analisys */
	char		       *END_OF_FILE;         /* gardian */
	int                    readAble;
	int                    arg_entry_num;
	int                    read_entry_num;
	char*                  program_name;
	char*                  arg_inputfile;
	uint                   log_header_magic;
	long                   log_header_version;
	int                    log_buffer_buf_ver;

	/* get argument */
	arg_entry_num = pointget->arg_entry_num;
	program_name  = pointget->program_name;
	arg_inputfile = pointget->arg_inputfile;

	fp=fopen(arg_inputfile, LKST_LOG_FMT_FILE_OPEM_MODE);
	if (fp==NULL) { 
		printf("%s: can't open %s\n\n", program_name, arg_inputfile);
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}

	stat(arg_inputfile,&info);
	fdata = malloc(info.st_size);
	if (fdata == NULL) {
		printf("%s: can't malloc memory of filedata\n\n", program_name);
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}

	readAble=fread(fdata, info.st_size, 1, fp);                 /* get filedata */
	if (readAble != 1) {
		printf("%s: failure read file-%s\n\n", program_name, arg_inputfile);
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}
	fclose(fp);

	evr = (struct lkst_log_record **)malloc( ( info.st_size/sizeof(struct posix_log_entry) )
								*sizeof(struct lkst_log_record *) );
	if (evr == NULL) {
		printf("can't malloc memory\n");
		printf("%s: can't malloc memory of pointer EventStructArray\n\n", program_name);
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}

	offset = (char *)fdata;
	END_OF_FILE = ((char *)fdata+info.st_size);

	/* get header_data */
	log_header_magic   = (((struct log_header *)offset)->log_magic);
	log_header_version = ((struct log_header *)offset)->log_version;
	/* comparing of log_magic and log_version */
	if ((log_header_magic != LOGFILE_MAGIC) || (log_header_version != 0)) {
		fprintf(stderr, " error of log_magic or log_version un-comparing : %d %ld\n",
							log_header_magic, log_header_version );
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}

	offset += sizeof(log_header_t);
	read_entry_num=0;

	/* analysis of the data between header and real eventdata */
	offset += sizeof(struct posix_log_entry) + sizeof(int);
	log_buffer_buf_ver = *(int *)offset;
	/* comparing of buf_ver */
	if (log_buffer_buf_ver != LKST_BUF_VER) {
		fprintf(stderr, "un-comparing of buf_ver error: %d\n", log_buffer_buf_ver);
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}
	offset += sizeof(int) + sizeof(char)*LKST_ARCH_NAME_LEN;

	/* body analizing*/
	
	while(offset<END_OF_FILE) {
		/* comparing */
		evr[read_entry_num]=(struct lkst_log_record *)offset;
		offset += sizeof(struct posix_log_entry) + 
			evr[read_entry_num]->posix.log_size;
		if (evr[read_entry_num]->posix.log_magic == LKST_LOG_MAGIC_NUM) {
			read_entry_num++;
		}
	}

	if (arg_entry_num < 0) {
		arg_entry_num = read_entry_num;
	}

	/* return argument */
	pointget->arg_entry_num  = arg_entry_num;
	pointget->read_entry_num = read_entry_num;
	pointget->fdata          = fdata;
	pointget->evr            = evr;
	return LKST_LOG_FMT_RET_CODE_TRUE;
}

static int make_pointerarray(struct lkst_arg_make_pointerarray *pointarr)
{
	int                    malloc_size;
	unsigned long          *fdata;
	struct lkst_log_record **evr;
	unsigned long          *offset;
	unsigned long          size;
	unsigned long          *END_OF_FILE;
	int                    i;
	int                    arg_entry_num;
	int                    read_entry_num;
	char*                  program_name;

	/* get argument */
	program_name   = pointarr->program_name;
	arg_entry_num  = pointarr->arg_entry_num;
	fdata          = pointarr->fdata;
	malloc_size    = pointarr->malloc_size;

	evr = (struct lkst_log_record **)malloc( ( malloc_size/sizeof(struct posix_log_entry) )
								*sizeof(struct lkst_log_record **) );
	if (evr == NULL) {
		printf("can't malloc memory\n");
		printf("%s: can't malloc memory of pointer EventStructArray\n\n", program_name);
		return LKST_LOG_FMT_RET_CODE_FALSE;
	}

	offset = fdata;
	END_OF_FILE = (unsigned long *)((char *)fdata+malloc_size);

	offset = (unsigned long *)((char *)offset + sizeof(log_header_t));
	read_entry_num=0;

	for (i=0;offset<END_OF_FILE;i++) {
		if (*offset == LKST_MAGIC_CODE) {
			evr[read_entry_num]=(struct lkst_log_record *)offset;
			read_entry_num++;
		}

		size = ((struct lkst_log_record *)offset)->posix.log_size;
		offset = (unsigned long *)((char *)offset+sizeof(struct posix_log_entry)+size);
	}

	if (arg_entry_num < 0){
		arg_entry_num = read_entry_num;
	}

	/* return argument */
	pointarr->arg_entry_num  = arg_entry_num;
	pointarr->read_entry_num = read_entry_num;
	pointarr->evr            = evr;
	return LKST_LOG_FMT_RET_CODE_TRUE;
}

int cfnc_ascending(const void *pointer1, const void *pointer2);
int cfnc_descending(const void *pointer1, const void *pointer2);

static int sort_data(struct lkst_arg_sort_data *pointsor)
{
	unsigned long          *fdata;
	struct lkst_log_record **evr;
	int                    arg_sort_flag;
	int                    read_entry_num;

	/* get argument */
	arg_sort_flag  = pointsor->arg_sort_flag;
	read_entry_num = pointsor->read_entry_num;
	fdata          = pointsor->fdata;
	evr            = pointsor->evr;

	if (arg_sort_flag) {
		qsort(evr, read_entry_num, sizeof(struct lkst_log_record *), cfnc_ascending);
	} else {
		qsort(evr, read_entry_num, sizeof(struct lkst_log_record *), cfnc_descending);
	}
	return LKST_LOG_FMT_RET_CODE_TRUE;
}

int cfnc_ascending(const void *pointer1, const void *pointer2)
{
	struct lkst_log_record *w1;
	struct lkst_log_record *w2;

	w1 = *(struct lkst_log_record **)pointer1;
	w2 = *(struct lkst_log_record **)pointer2;

	if ((signed long)(w1->posix.log_time.tv_sec)==(signed long)(w2->posix.log_time.tv_sec)) {
		return (signed long)(w1->posix.log_time.tv_nsec) - (signed long)(w2->posix.log_time.tv_nsec);
	}
	return (signed long)(w1->posix.log_time.tv_sec) - (signed long)(w2->posix.log_time.tv_sec);
}

int cfnc_descending(const void *pointer1, const void *pointer2)
{
	struct lkst_log_record *w1;
	struct lkst_log_record *w2;

	w1 = *(struct lkst_log_record **)pointer1;
	w2 = *(struct lkst_log_record **)pointer2;

	if ((signed long)(w1->posix.log_time.tv_sec)==(signed long)(w2->posix.log_time.tv_sec)) {
		return (signed long)(w2->posix.log_time.tv_nsec) - (signed long)(w1->posix.log_time.tv_nsec);
	}
	return (signed long)(w2->posix.log_time.tv_sec) - (signed long)(w1->posix.log_time.tv_sec);
}

static int print_data(struct lkst_arg_print_data *pointpri,int arg_csv_flag)
{
	int                    i, j;                                  /* roop flag */
	int                    out_Entry_num;                         /* The number of output items */
	int                    arg_entry_num;
	int                    arg_cpu_id;                            /* cpu_id */
	int                    arg_filter_flag;
	int                    event_type_num;
	char                   event_Name_str[LKST_LOG_FMT_SORT_BUF_SIZE]; /* work */
	struct lkst_log_record **evr;
	unsigned long          *fdata;

	/* get argument */
	arg_entry_num   = pointpri->arg_entry_num;
	arg_cpu_id      = pointpri->arg_cpu_id;
	arg_filter_flag = pointpri->arg_filter_flag;
	fdata           = pointpri->fdata;
	evr             = pointpri->evr;

	for (i=0,out_Entry_num=0; i<(signed int)arg_entry_num ;i++) {
		if ((arg_cpu_id >= 0)&&(arg_cpu_id != (signed long)evr[i]->posix.log_processor)) {
			continue;
		}
		event_type_num = evr[i]->posix.log_event_type;

		/* event filter */
		if (arg_filter_flag) {
			if (LKST_event_data[event_type_num].LKST_filter != 1) {
				continue;
			}
		}

		/* error about event_type_num */
		if ((event_type_num >= LKST_ETYPE_MAX) ||
		    (event_type_num <= 0) ||
		    (LKST_event_data[event_type_num].LKST_event_name == NULL)) {
			continue;
		}

		/* display event_type */
		strncpy(event_Name_str, 
			LKST_event_data[event_type_num].LKST_event_name,
			LKST_LOG_FMT_SORT_BUF_SIZE-1);
		event_Name_str[LKST_LOG_FMT_SORT_BUF_SIZE-1]='\0';
		
		if (strcmp( event_Name_str, "" )==0) {
			/* event_data undefined ? */
			if ( arg_csv_flag )
				printf("0x%08x,", event_type_num);
			else
				printf("event_type=0x%08x\n", event_type_num);
		} else {
			/* display  event name */
			if ( arg_csv_flag )
				printf("\"%s\",", event_Name_str);
			else
				printf("event_type=%s\n", event_Name_str);
		}
		/* display cpu pid time */
		if ( arg_csv_flag )
			printf("%02u,%08u,", evr[i]->posix.log_processor, evr[i]->posix.log_pid);
		else
			printf("\tcpu=%02u, pid=%08u\n", evr[i]->posix.log_processor, evr[i]->posix.log_pid);
		clock_viewer((unsigned long)evr[i]->posix.log_time.tv_sec, (unsigned long)evr[i]->posix.log_time.tv_nsec,arg_csv_flag);
		/* display args_data */
		for ( j=0; j<4; j++) {
			if (( LKST_event_data[event_type_num].LKST_inf_args[j] != 0x00) &&
			    (strcmp( LKST_event_data[event_type_num].LKST_inf_args[j], "") != 0)) {
				if ( arg_csv_flag )
					printf("\"%s\",0x%08x,0x%08x",
					       LKST_event_data[event_type_num].LKST_inf_args[j],
					       *((uint *)(&(evr[i]->log_arg1)+j)),
					       *((uint *)(&(evr[i]->log_arg1)+j)+1)
					       );
				else
					printf("\targ%d=0x%08x %08x : %s\n",
					       j+1,
					       *((uint *)(&(evr[i]->log_arg1)+j)),
					       *((uint *)(&(evr[i]->log_arg1)+j)+1),
					       LKST_event_data[event_type_num].LKST_inf_args[j]
					       );
			}
		}
		printf("\n");
		out_Entry_num++;
		if (out_Entry_num >= arg_entry_num) {
			break;
		}
	}
	if (out_Entry_num == 0) {
		printf("No data.\n");
	}
	return LKST_LOG_FMT_RET_CODE_TRUE;
}

void help_viewer(char* program_name)
{
	int   idx;               /* roop flag */

	printf("usage: \n");
	printf("%s print [options]\n", program_name);
	printf("   -f file_name          file_name\n");
	printf("   -c cpu_id             cpu id\n");
	printf("   -e event_name ...     event filter\n");
	printf("                         The event_name which can be specified is as follows.\n");
	for (idx=LKST_EDATA_ID_MIN; idx<=LKST_EDATA_ID_MAX; idx++) {
		if (( LKST_event_data[idx].LKST_event_name != 0x00) &&
		    (strcmp( LKST_event_data[idx].LKST_event_name, "") != 0)) {
			printf("                           %s\n", LKST_event_data[idx].LKST_event_name);
		}
	}
	printf("                           all\n");
	printf("   -h                    help\n");
	printf("   -n entry_num          the number of output entry\n");
	printf("   -r                    reverse the result of comparisons\n");
	printf("                         (default : descending sort)\n");
}

void clock_viewer(unsigned long time_sec, unsigned long time_usec,int arg_csv_form)
{
	struct tm *newtime;
	time_t    ltime;
	char      monthName[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
	char      weekdayName[7][4]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};

	ltime = (time_t)time_sec;
	newtime = localtime( &ltime );
	if ( arg_csv_form )
	{
	printf( "%s,%s,%02d,%02d:%02d:%02d.%09lu,%04d,",
		weekdayName[newtime->tm_wday],
		monthName[newtime->tm_mon],
		newtime->tm_mday,
		newtime->tm_hour,
		newtime->tm_min,
		newtime->tm_sec,
		time_usec,
		newtime->tm_year + LKST_LOG_FMT_PRINT_SIZE);
	}
	else
	{
	printf( "\ttime=%s %s %02d %02d:%02d:%02d.%09lu %04d\n",
		weekdayName[newtime->tm_wday],
		monthName[newtime->tm_mon],
		newtime->tm_mday,
		newtime->tm_hour,
		newtime->tm_min,
		newtime->tm_sec,
		time_usec,
		newtime->tm_year + LKST_LOG_FMT_PRINT_SIZE);
	}
}

