#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>

void error(char* reason, const char* msg)
{
  fprintf(stderr,"%s - %s",reason,msg);
  return;
}

int a=1; /*0 - no; 1 - 8; 2- hex; 3 - 10*/
int b=16; /*size of block*/
int z[8][2]; /*count-type*/
int zcount=0;

int fileprint;

void output(FILE* f)
{
  if(zcount==0)
  {
    z[zcount][0]=4;
    z[zcount][1]=1;
    zcount++;
  }
  long long filepos=0;
  int curz=0;
  int l;
  char block[1024];
  int k,p;
  char fmt[10];
  char c;
  unsigned long long n;
  while(!feof(f))
  {
    k=fread(block,1,b,f);
    if(k!=0)
    for(curz=0;curz<zcount;curz++)
    {
      printf("\n");
      switch(a)
      {
      case 1:
        printf("%10llo: ",filepos); break;
      case 2:
        printf("%10llx: ",filepos); break;
      case 3:
        printf("%10lld: ",filepos); break;
      }
      for(p=0;p<k;p+=z[curz][0])
      {
        n=0;
        if(z[curz][1]==0 || z[curz][1]==1 ||z[curz][1]==3)
        {
          switch(z[curz][0])
          {
          case 1: n=*((unsigned char*)     &block[p]); break;
          case 2: n=*((unsigned short*)    &block[p]); break;
          case 4: n=*((unsigned int*)      &block[p]); break;
          case 8: n=*((unsigned long long*)&block[p]); break;
          }
        }
        if(z[curz][1]==2)
        {
          switch(z[curz][0])
          {
          case 1: n=*((char*)     &block[p]); break;
          case 2: n=*((short*)    &block[p]); break;
          case 4: n=*((int*)      &block[p]); break;
          case 8: n=*((long long*)&block[p]); break;
          }
        }
        if(z[curz][1]==0 || z[curz][1]==1 ||z[curz][1]==3)
        {
          if(z[curz][1]==0) l=(int)ceil(z[curz][0]/(3.0/8.0));
          if(z[curz][1]==1) l=(int)ceil(z[curz][0]/(4.0/8.0));
          if(z[curz][1]==3) 
          {
            if(z[curz][0]==1) l=3;
            if(z[curz][0]==2) l=5;
            if(z[curz][0]==4) l=10;
            if(z[curz][0]==8) l=20;
          }
          switch(z[curz][1])
          {
          case 0: c='o'; break;
          case 1: c='x'; break;
          case 3: c='u'; break;
          }
          sprintf(fmt," %%0%dll%c\0",l,c);
          printf(fmt,n);
        }
        else
        {
          if(z[curz][0]==1) l=4;
          if(z[curz][0]==2) l=6;
          if(z[curz][0]==4) l=11;
          if(z[curz][0]==8) l=21;
          sprintf(fmt," %%%dlld\0",l,c);
          printf(fmt,n);
        }
      }
    }
    filepos+=b;
  }
  printf("\n");
  printf("\n");
}


int main(int argc, char** argv)
{
  int i;
  int options=1;
    
  for(i=1;i<argc;i++)
  {
    if(strcmp(argv[i],"--")==0)
      {
        break;
      }
    if(argv[i][0]=='-' && argv[i][1]!=0 && options)
    {
      // d output
      if(argv[i][1]=='a')
      {
        switch(argv[i][2])
        {
        case '0': a=0; break;
        case 'o': a=1; break;
        case 'x': a=2; break;
        case 'd': a=3; break;
        default: error(argv[i],"unhandled parameter (must be -a0 or -ao or -ax or -ad)"); return 2;
        }
      }
      // size of block      
      else if(argv[i][1]=='b')
      {
        int n=0,j;
        for(j=2;isdigit(argv[i][j]);j++)
        {
          n*=10;
          n+=argv[i][j]-'0';
        }
        if(argv[i][j]!=0)
        {
          error(argv[i],"unhandled parameter (must be -b[number])");
          return 2;
        }
        b=n;
      }
      //format
      else if(argv[i][1]=='1' || argv[i][1]=='2' || argv[i][1]=='4' || argv[i][1]=='8')
      {
        int Z,C;
        switch(argv[i][1])
        {
        case '1': Z=1; break;
        case '2': Z=2; break;
        case '4': Z=4; break;
        case '8': Z=8; break;
        default: error(argv[i],"unhandled parameter (must be -ZC, Z=(1|2|4|8), C=(o|x|d|u))"); return 2;
        }
        switch(argv[i][2])
        {
        case 'o': C=0; break;
        case 'x': C=1; break;
        case 'd': C=2; break;
        case 'u': C=3; break;
        default: error(argv[i],"unhandled parameter (must be -ZC, Z=(1|2|4|8), C=(o|x|d|u))"); return 2;
        }
        z[zcount][0]=Z;
        z[zcount][1]=C;
        zcount++;
      }
      else if(strcmp(argv[i],"-help")==0)
      {
        printf("%s","Outputs the given file(s) using the given template(s)\nOD [OPTIONS] [FILES]\nOD -help\n\nPossible options:\n-a[0|o|x|d] Do not output position in file | output it in oct | hex | dec\n-b[number] Output [number] bytes in each line\n-[1|2|4|8][o|x|d|u] Output blocks with size 1|2|4|8 bytes in oct | hex | signed dec | unsigned dec format\n-- stop command line handling\n\nUse - for input from stdin istead of file\n\n");
        return 0;
        //help
      }
      else
      {
        error(argv[i],"unhandled parameter"); 
        return 2;
      }
    }
    else
    {
      options=0;
      //it is file
      FILE* f;
      if(argv[i][1]==0)
      {
        f=stdin;
        printf("%s","STDIN\n");
      }
      else
      {
        printf("%s\n",argv[i]);
        f=fopen(argv[i],"r");
        if(f==0)
        {
          error(argv[i],"error while opening file");
          //return 2;
        }
      }
      if(f!=0)
        output(f);
    }
  }
  return 0;
}
