/* Dump - display file in binary decimal ASCII or hex */
/* Microsoft C */
/******************************************************
Nigel Salt
25 Lower Station Rd
Crayford
Kent
DA1 3PY
UK

Phone +44 322 553260

Email nao@cix.complink.co.uk
******************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXWID 128

void pbin(char);
void usage(void);

void main(argc,argv)
int argc;
char *argv[];
{
  unsigned long l,start=0,len=160,count=0,curoff=0;
  int i,j,width=8,inch;
  char *cpres;
  char pic[5];
  enum {decimal,hex} offtyp=decimal;
  FILE *f;
  static unsigned char buff[MAXWID];

  if (argv[1][0]=='?') usage();

  cpres=strcpy(pic,"ha");

  for (i=1;i<argc && argv[i][0]=='-';i++)
    {
    switch (tolower(argv[i][1]))
      {
      case 'o':
        if (argv[i][2]=='h') 
          {
          offtyp=hex;
          }
        else
          {
          offtyp=decimal;
          }
        break;
      case 's':
        start=atol(&argv[i][2]);
        break;
      case 'w':
        width=atoi(&argv[i][2]);
        if (width==0) width=8;
        if (width>MAXWID) width=MAXWID;
        break;
      case 'l':
        len=atol(&argv[i][2]);
        if (len==0) len=160;
        break;
      case 'p':
        for (j=0;j<4 && argv[i][2+j]!='\0';j++)
          pic[j]=argv[i][2+j];
        pic[j]='\0';
        break;
      default:
        printf("\nUnknown switch: '%s'",argv[i]);
        usage();
      }
    }

  if (i==argc)
    {
    f=stdin;
    }
  else 
    {
    f=fopen(argv[i],"rb");
    if (f==NULL)
      {
      printf("\nCannot open '%s'",argv[i]);
      usage();
      }
    }

  for (l=0;l<start;l++)  
    inch=getc(f);

  printf("\nDump of file '%s'",argv[i]);

  for (l=0;l<len && inch!=EOF; l+=width)
    {
    if (offtyp==hex)
      {
      printf("\n%8.lX: ",start+l);
      }
    else
      {
      printf("\n%10.ld: ",start+l);
      }
    for (j=0;j<width;j++)
      {
      inch=getc(f);
      buff[j]=(char)inch;
      }
    for (i=0;i<4 && pic[i];i++)
      {
      for (j=0;j<width;j++)
        {
        switch (pic[i])
          {
          case 'a':
            printf("%c",(isprint(buff[j])?buff[j]:' '));
            if (j==(width-1)) printf(" ");
            break;
          case 'h':
            printf("%.2X ",buff[j]);
            break;
          case 'd':
            printf("%3.d ",buff[j]);
            break;
          case 'b':
            pbin(buff[j]);
            printf(" ");
            break;
          default:
            printf("\nUnknown option '%c' in -p switch",pic[i]);
            usage();
          }         /* End of -p switch */
        }           /* End of pic loop */
      }             /* End of print line for loop */
    }               /* End of dump for loop */
  printf("\n");
  exit(0);
}                   /* End of dump prog */

void pbin(x)
char x;
{
  printf("%c",(x&0x0080?'1':'0'));
  printf("%c",(x&0x0040?'1':'0'));
  printf("%c",(x&0x0020?'1':'0'));
  printf("%c",(x&0x0010?'1':'0'));
  printf("%c",(x&0x0008?'1':'0'));
  printf("%c",(x&0x0004?'1':'0'));
  printf("%c",(x&0x0002?'1':'0'));
  printf("%c",(x&0x0001?'1':'0'));
}

void usage()
{
  printf("\ndump - displays file in binary decimal hex or ASCII");
  printf("\nUSAGE");
  printf("\ndump [-switch] [-switch] filename");
  printf("\nSWITCHES");
  printf("\n-od display offset in decimal");
  printf("\n-oh display offset in hex");
  printf("\n-p  set up picture - any combination of");
  printf("\n    a ASCII");
  printf("\n    b binary");
  printf("\n    d decimal");
  printf("\n    h hex    ");
  printf("\n-wn display n bytes per line");
  printf("\n-sn start at byte number n");
  printf("\n-ln display n bytes");
  printf("\nDEFAULT ");
  printf("\ndump -od -pha -w8 -s0 -l160");
  exit(1);
}

