/*
#define	MAIN
*/
#define	DEBUG

#include	<stdio.h>
#include	<stdlib.h>
#include	<ctype.h>
#include	"types.h"
#include	"debug.h"

FILE	*dbgout;

extern	void
_DumpChar(
	char	c)
{
	if		(  isprint(c)  )	{
		printf("%c",c);
	} else {
		printf("<%02X>",(int)c);
		if		(  c  ==  '\n'  )	{
			printf("\n");
		}
	}
}

extern	void
_DumpArray(
	byte	*buf,
	size_t	size,
	PARAM	para)
{	size_t	i;
	byte	m;
	int		ch
	,		j;

	if		(  para  ==  PARA_NULL  )	{
		for	( i = 0 ; i < size ; i ++ )	{
			_DumpChar(buf[i]);
		}
		putchar('\n');
	}
	if		(  para  &  PARA_ASCII  )	{
		printf("A:");
		for	( i = 0 ; i < size ; i ++ )	{
			if		(  isprint(buf[i])  )	{
				ch = buf[i];
			} else {
				ch = '.';
			}
			printf("%c   ",ch);
		}
		putchar('\n');
	}
	if		(  para  &  PARA_BINARY  )	{
		printf("B:");
		for	( i = 0 ; i < size ; i ++ )	{
			m = 0x80;
			for	( j = 0 ; j < 8 ; j ++ )	{
				if		(  m  &  buf[i]  )	{
					if		(  para & PARA_SET  )	{
						putchar('*');
					} else {
						putchar('1');
					}
				} else {
					if		(  para & PARA_SET  )	{
						putchar(' ');
					} else {
						putchar('0');
					}
				}
				m >>= 1;
			}
			putchar(' ');
		}
		putchar('\n');
	}
	if		(  para  &  PARA_OCTAL  )	{
		printf("O:");
		for	( i = 0 ; i < size ; i ++ )	{
			printf("%3.3o ",(int)buf[i]);
		}
		putchar('\n');
	}
	if		(  para  &  PARA_DECIMAL  )	{
		printf("D:");
		for	( i = 0 ; i < size ; i ++ )	{
			printf("%3.3d ",(int)buf[i]);
		}
		putchar('\n');
	}
	if		(  para  &  PARA_HEX  )	{
		printf("H:");
		for	( i = 0 ; i < size ; i ++ )	{
			printf("%2.2X  ",(int)buf[i]);
		}
		putchar('\n');
	}
}

extern	void
_dbgmsg(
	char	*s)
{
	printf("%s\n",s);
	fflush(stdout);
#if	0
	getchar();
#endif
}

extern	void
_error(
	char	*msg,
	char	*file,
	int		line)
{
	fprintf(stderr,"error:%s(%d):%s\n",file,line,msg);
	fflush(stderr);
	exit(1);
}

extern	void
_dbgopen(
	char	*name)
{
	if		(  name  ==  NULL  ) {
		dbgout = fopen("debug.out","a");
	} else {
		dbgout = fopen(name,"a");
	}
}

extern	void
_dbgclose(void)
{
	if		(  dbgout  !=  stdout  ) {
		fclose(dbgout);
	}
}


#ifdef	MAIN
#include	<string.h>
#include	<fcntl.h>
#include	<io.h>
void
ExecDump(
	FILE	*fp,
	PARAM	para,
	int		width,
	long	off_start,
	long	off_end)
{	int		i
	,		size;
	char	*buf
	,		*p;
	long	ofs;
	byte huge	*adrs;

	buf = (char *)malloc(width);
	if		(  fp  !=  NULL  )	{
		fseek(fp,off_start,SEEK_SET);
	} else {
		adrs = (byte huge *)off_start;
	}
	ofs = off_start;
	do	{
		if		(  fp  !=  NULL  )	{
			size = fread(buf,1,width,fp);
			if		(	(  off_end  !=  0L  )
					 &&	(  ofs  >  off_end  ) )	{
				size = off_end - ofs;
			}
		} else {
			if		(  adrs  <  (byte huge *)off_end  )	{
				for	( i = 0 , p = buf ; i < width ; i ++ , adrs ++ )	{
					*p = *adrs;
				}
				size = width;
			} else {
				size = 0;
			}
		}
		printf("%8.8lX\n",ofs);
		_DumpArray(buf,size,para);
		ofs += size;
	}	while	(  size  ==  width  );
}

static	void
PrintHelp(void)
{	printf("dump <option> [<file>]\n");
	printf("<option>\n");
	printf("\t-A:ascii\n");
	printf("\t-B:binary\n");
	printf("\t-O:octal\n");
	printf("\t-D:decimal\n");
	printf("\t-H:hexdecimal\n");
	printf("\t-C:with character(hex dump only)\n");
	printf("\t-*:supress 0\n");
	printf("\t-Wn:data width\n");
}

int
main(
	int		argc,
	char	*argv[])
{	FILE	*fpInput;
	int		i
	,		width;
	char	*p
	,		*fn;
	PARAM	para;
	long	off_start
	,		off_end;

	if		(  argc  ==  1  )	{
		PrintHelp();
		exit(0);
	} else {
		fn = NULL;
		para = PARA_NULL;
		width = 16;
		off_start = 0L;
		off_end = 0L;
		for	( i = 1 ; i < argc ; i ++ )	{
			p = argv[i];
			if		(  *p  ==  '-'  )	{
				p ++;
				while	(  *p  !=  '\0'  )	{
					switch	(*p)	{
					  case	's':
					  case	'S':
						p ++;
						off_start = atol(p);
						break;
					  case	'e':
					  case	'E':
						p ++;
						off_end = atol(p);
						break;
					  case	'c':
					  case	'C':
						para |= PARA_CHAR;
						break;
					  case	'a':
					  case	'A':
						para |= PARA_ASCII;
						break;
					  case	'o':
					  case	'O':
						para |= PARA_OCTAL;
						break;
					  case	'h':
					  case	'H':
						para |= PARA_HEX;
						break;
					  case	'd':
					  case	'D':
						para |= PARA_DECIMAL;
						break;
					  case	'b':
					  case	'B':
						para |= PARA_BINARY;
						break;
					  case	'*':
						para |= PARA_SET;
						break;
					  case	'w':
					  case	'W':
						width = atoi(p+1);
						break;
					  default:
						break;
					}
					p ++;
				}
			} else {
				fn = p;
			}
		}
	}
	if		(  fn  ==  NULL  )	{
		fpInput = stdin;
		setmode(fileno(fpInput),O_BINARY);
	} else {
		if		(  !stricmp(fn,"/dev/mem")  )	{
			fpInput = NULL;
		} else {
			if		(  ( fpInput = fopen(fn,"rb") )  ==  NULL  )	{
				fprintf(stderr,"file not found\n");
				exit(1);
			}
		}
	}
	if		(  para  ==  PARA_NULL  )	{
		para = PARA_HEX | PARA_CHAR;
	}
	ExecDump(fpInput,para,width,off_start,off_end);
}
#endif

