static char sccsid[]="%Z% %M% %I% %E% %U%";
/********************************************/
/*											*/
/*	  coded by A.Kobayashi 2013.09.29		*/
/*											*/
/********************************************/
#include "akxcommon.h"

#define D_DUMP_SIZE 16
#define D_MAX_ILINE 16

static char *gcHeader="  addr    loc   0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 ----+----+----+-";

/********************************************************/
/*														*/
/********************************************************/
int akxafxdmp_optv(FILE *fp, char *msg, char *p_str, int str_len, int argc, char *argv[])
{
	char buf[D_DUMP_SIZE*3+1],buf2[D_DUMP_SIZE+5],*p;
	int i,iend,line,i_line;
	int kanji,kflg,isave[4],usage;
	int iMaxLine,iMaxILine,type,opt_out[4];

	if (!p_str) return -101;
	if (fp == stdin) return -102;
	if (!msg) msg = "";
	if (!fp) fp = stdout;
	iMaxLine = -1;
	iMaxILine = D_MAX_ILINE;
	type = akxt_get_code_type();
	if (argc>0 && argv) {
		if (usage = chkopt(argc,argv,opt_out)) return -103;
		iMaxLine = opt_out[0];
		iMaxILine = opt_out[1];
		type = opt_out[2];
	}
	kanji = kflg = 0;
	isave[0] = isave[1] = 0;
	isave[2] = -1;
	isave[3] = type;
	i_line = line = 0;
	printf("***** %s *****\n%s",msg,gcHeader);
	iend = str_len;
	p = p_str;
	for (i=0;i<iend;i+=D_DUMP_SIZE,p+=D_DUMP_SIZE) {
		if (iMaxLine >= 0) {
			line++;
			if (line > iMaxLine) break;
		}
		if (iMaxILine > 0 ) {
			i_line++;
			if (i_line > iMaxILine) {
				printf("\n\n%s",gcHeader);
				i_line = 1;
			}
		}
		kflg = make_xdline(buf,buf2,p,iend-i,isave);
		kanji = isave[0];
		printf("\n%08x%6d%s %s",p,i,buf,buf2);
	}
	fprintf(fp,"\n%08x%6d (DATA END)\n",p,iend);
	return 0;
}

/********************************************************/
/*														*/
/********************************************************/
int akxafxdmp_opt(FILE *fp, char *msg, char *p_str, int str_len, char *opt)
{
	char *argv[16],parm[128];
	int  argc;

	if (opt) {
		argc = akxtgetargvn2(opt,strlen(opt),argv,16,parm,sizeof(parm),0);
	}
	else {
		argc = 0;
	}
	return akxafxdmp_optv(fp,msg,p_str,str_len,argc,argv);
}

/********************************************************/
/*														*/
/********************************************************/
int akxafixdmp_opt(char *out_file, char *msg, char *p_str, int str_len, char *opt)
{
	FILE *fp;
	char c,*open_mode,*argv[16],parm[128],*p,**pav;
	int rc,argc,argc0;

	if (!p_str) return -1;
	if (!out_file) out_file = "";
	if ((c=*out_file)=='\0' || c=='-') {
		rc = akxafxdmp_opt(stdout,msg,p_str,str_len,opt);
	}
	else {
		argc0 = argc = akxtgetargvn2(opt,strlen(opt),argv,16,parm,sizeof(parm),0);
		pav = argv;
		open_mode = "w";
		while (argc--) {
			p = *pav++;
			if (*p == '-') {
				c = *(p+1);
				if (c == 'a') open_mode = "a";
				else if (c == 'w') open_mode = "w";
			}
		}
		if (fp=fopen(out_file,open_mode)) {
			rc = akxafxdmp_optv(fp,msg,p_str,str_len,argc0,argv);
			fclose(fp);
		}
		else {
			printf("file[%s] open error!!\n",out_file);
			rc = -2;
		}
	}
	return rc;
}

/********************************************************/
/*														*/
/********************************************************/
int make_xdline(char *pw, char *pw2, char *p, int iend, int isave[])
{
	char *pp;
	int j,jj,k,kanji,mlen,kflg,j0;

	kanji = isave[0];
	kflg = isave[1];
	j0 = isave[2];
	if (j0 > 0) {
		p += j0;
		pw += strlen(pw);
		pw2 += strlen(pw2);
		isave[2] = 0;
	}
	else {
		if (j0 < 0) j0 = 0;
		pp = p;
		for (j=j0;j<D_DUMP_SIZE;j++) {
			if (j < iend) {
				sprintf(pw," %02x",(int)*pp++ & 0xff);
				pw += strlen(pw);
			}
			else {
				*pw++ = ' ';
				*pw++ = ' ';
				*pw++ = ' ';
			}
		}
	}

	if ((jj=D_DUMP_SIZE) > iend) jj = iend;
	for (j=j0;j<D_DUMP_SIZE;) {
		if (j >= jj) break;
		if (j==0 && kflg>0) {
			for (k=0;k<kflg;k++) {
				if (kanji > 0) *pw2++ = ' ';
				else *pw2++ = '.';
				j++;
				p++;
			}
			kflg = 0;
		}
		else {
			if ((mlen=akxqkanjilen2(p,iend-j))>1) {
				if (mlen == 103) {
					kanji = -1;
					mlen = 3;
				}
				else kanji = 1;
			}
			else if (mlen<0 && isave[2]>=0) {
				kflg = j - iend;
				isave[2] = j;
/*
printf("\nmake_xdline1 iend=%d j=%d kanji=%d mlen=%d".iend,j,kanji,mlen):
*/
				break;
			}
			else kanji = 0;
/*
printf("\n iend=%d j=%d kanji=%d m1en=%d",iend,j,kanji,mlen);
*/
			if (kanji) {
				if (kanji > 0) {
					*pw2++ = *p;
					*pw2++ = *(p+1);
					if (mlen >= 3) *pw2++ = *(p+2);
					if (mlen >= 4) *pw2++ = *(p+3);
				}
				if ((kflg=j+mlen-D_DUMP_SIZE) > 0) {
					mlen -= kflg;
				}
				else {
					kflg = 0;
					if (kanji > 0) {
						if (mlen >= 3) *pw2++ = ' ';
						if (mlen >= 4) *pw2++ = ' ';
					}
				}
				for (k=0;k<mlen;k++) {
					j++;
					p++;
					if (kanji < 0) *pw2++ = '.';
				}
			}
			else {
				*pw2++ = akxctoank(*p);
				j++;
				p++;
			}
		}
	}
	*pw = '\0';
	*pw2 = '\0';
	isave[0] = kanji;
	isave[1] = kflg;
	return kflg;
}

/********************************************************/
/*														*/
/********************************************************/
int chkopt(int argc, char *argv[], int opt[])
{
	int usage,type,iMaxLine,iMaxILine;
	char c,*p,*file,*open_mode;

	iMaxLine = -1;
	iMaxILine = D_MAX_ILINE;
	type = akxt_get_code_type();
	open_mode = "w";
	usage = 0;
	file = NULL;
	while (argc-- > 0) {
		if (file) {
			usage = 1;
			break;
		}
		p = argv[0];
		if (*p == '-') {
			c = *(p+1);
			if (c == '\0') {
				file = p;
			}
			else if (c>='0' && c<='9') iMaxLine = atoi(p+1);
			else {
				p++;
				while (c=*p++) {
					if (c == 't') {
						iMaxILine = atoi(p);
						break;
					}
					else if (c == 'b') type = 0;
					else if (c == 'e') type = CD_TYPE_EUC;
					else if (c == 's') type = CD_TYPE_SJIS;
					else if (c == 'u') type = CD_TYPE_UTF8;
					else if (c == 'a') open_mode = "a";
					else if (c == 'w') open_mode = "w";
					else {
						usage = 1;
						break;
					}
				}
				if (usage) break;
			}
		}
		else {
			file = p;
		}
		argv++;
	}
	if (file) usage = 1;
	opt[0] = iMaxLine;
	opt[1] = iMaxILine;
	opt[2] = type;
	memcpy(&opt[3],open_mode,2);
	return usage;
}

/********************************************************/
/*														*/
/********************************************************/
int akxafxdmp(fp,msg,dat,len)
FILE *fp;
char *msg,*dat;
int  len;
{
#if 1
	return akxafxdmp_opt(fp,msg,dat,len,NULL);
#else
	int i,j,jj,iend;
	int kanji,kflg;
	char *p,*pp,buf[128],pb[8];

	if (!fp) return -1;
	if (msg) fprintf(fp,"*** %s ***\n",msg);
	if (!dat) return 0;
	if (len <= 0) return len;
	fprintf(fp,gcHeader);

	kanji = kflg = 0;
	p = dat;
	iend = len;
	for (i=0;i<iend;i+=16) {
		sprintf(buf,"\n%08x %05d",p,i);
		pp = p;
		if ((jj=i+16) > iend) jj = iend;
		for (j=i;j<i+16;j++) {
			if (j < iend) {
				sprintf(pb," %02x",(int)*pp++ & 0xff);
				strcat(buf,pb);
			}
			else strcat(buf,"   ");
		}
		strcat(buf," ");
		for (j=i;j<jj;j++,p++) {
			if (j==i && kflg) {
				strcpy(pb," ");
				kflg = 0;
			}
			else {
				if ((j<iend-1) && akxqiskanji(p)) kanji = 1;
				else kanji = 0;
				if (kanji) {
					sprintf(pb,"%c%c",*p,*(p+1));
					if (j < jj-1) {
						j++;
						p++;
					}
					else kflg = 1;
				}
				else sprintf(pb,"%c",akxctoank(*p));
			}
			strcat(buf,pb);
		}
		fprintf(fp,"%s",buf);
	}
	fprintf(fp,"\n%08x %05d (DATA END)\n",p,j);
	return len;
#endif
}

/********************************************************/
/*														*/
/********************************************************/
int akxaxdump(msg,dat,len)
char *msg,*dat;
int  len;
{
	return akxafxdmp(stdout,msg,dat,len);
}

/********************************************************/
/*														*/
/********************************************************/
int akxafixdmp(file,msg,dat,len)
char *file,*msg,*dat;
int  len;
{
#if 1
	return akxafixdmp_opt(file,msg,dat,len,"-a");
#else
	FILE *fp;
	int ret;

	if (file) {
		if (fp = fopen(file,"a")) {
			ret = akxafxdmp(fp,msg,dat,len);
			fclose(fp);
		}
		else ret = -1;
	}
	else ret = akxaxdump(msg,dat,len);
	return ret;
#endif
}
