/*******************************************************/
/*                   1.2.3.A.mon                       */
/*                                                     */
/*                         MON                         */
/*                  (c) Bruno Jennrich                 */
/*                                                     */
/*                                                     */
/* This program outputs a memory range                 */
/* as a hex dump.                                      */
/*******************************************************/

#define WIDTH 12L        /* number of bytes to display */
#define MASK (255L-32L) /* for conversion to uppercase */

unsigned char Conversion_Table[256];
                                   /* conversion table */
unsigned char *lowadress,  /* lowest address to be displayed */
              *highadress; /* highest address to be displayed */

unsigned char *pos;     /* current address or position */
                                         /* in memory  */

unsigned char *atoh (String)    /* digit string to hex */
char                *String;
{
   int i;
   unsigned char *hex;                       /* result */
   unsigned long factor;               /* place factor */

   hex = (unsigned char *)0L;            /* result = 0 */
   factor = 1L;         /* factor equals 1 (one place) */

   if (strlen (String) <= 8) /* more than eight characters */
      for (i=(strlen(String)-1);i>=0;i--)
      {
         if ((String[i] >= '0') && (String[i] <= '9'))
         {                     /* figures */
            hex += (String[i] - '0')*factor;
            factor *= 0x10;
         }

         if (((String[i] & MASK) >= 'A') &&
             ((String[i] & MASK) <= 'F'))
         {                     /* Hex-figures */
            hex += ((String[i] & MASK)-'A'+0xa)*factor;
            factor *= 0x10;
         }
      }

   return (hex);
}

main (argc, argv)
int   argc;
char      **argv;
{
   int i;
   if (argc != 3)     /* number of parameters is wrong */
   {
      printf ("USAGE: mon START END\n");
      exit (10);
   }

  lowadress  = atoh (argv[1]); /* calculate lowest and */
  highadress = atoh (argv[2]);    /* highest addresses */

   if (lowadress > highadress)       /* error in input */
   {
      printf ("START must be less than END !!!\n");
      exit (10);
   }

   for (i=0;i<32 ;i++) Conversion_Table[i] = '.';
   for (   ;i<128;i++) Conversion_Table[i] = (char)i;
   for (   ;i<160;i++) Conversion_Table[i] = '.';
   for (   ;i<256;i++) Conversion_Table[i] = (char)i;
                             /* build conversion table */

   pos = lowadress;         /* current position equals */
                                       /*lowest adress */

   while (pos < highadress)             /* output loop */
      if ((long) (highadress-pos) >= WIDTH) Show (WIDTH);
      else  Show ((long) (highadress-pos));
}

Show (ok)
long ok;
{
   int i;

   printf ("$%08lx   ",pos);        /* output position */

   for (i=0;i<ok;i++)
     printf ("$%02x ",*(pos+i)); /* output byte as hex */

   if (ok < WIDTH) for (   ;i<WIDTH;i++)
      printf ("    ");              /* fill space with */
                                             /* blanks */
   printf (" ");

   for (i=0;i<ok;i++)
      printf ("%c",Conversion_Table[*(pos++)]);
                                       /* bytes as hex */

   printf("\n");                    /* carriage return */
}

