/***************************************************************************
*
*   Copyright P.J.Ruczynski 1990
*   This software is free for redistribution and re-use as long as this
*   copyright is included in all source files. This software is supplied
*   as is and no responsibilty is taken by the author for any problems
*   arising from this code.
*
* File name        -  hexprint.c
*
* Module name        -  HEXPRINT
*
* Author        -  P.J.Ruczynski    <pjr@pyra.co.uk>
*
* First Release        -  16 Feb 1990
*
* Version number    -  1.4
*
* Description        -  A hexadecimal printing routine, will print the 
*                          given buffer with the hex on the left and the 
*                          ascii on the right.
*
*            Revision List
*
* pjr    08.05.89    Added offset numbering. This can be compiled out for
*            optimum performance.
*
* pjr    11.05.89    Added compressed output format. This can be compiled
*            out for optimum performance.
*
* pjr    02.08.89    Changed the bcopy and bcmp routines to use defines 
*                       defined  in hexprint.h and controlled by compilation 
*                       flag 'ATT'. With this defined att routines are used, 
*                       default means bsd routines are used. Note that the 
*                       compression stuff uses BCMP and BCOPY.
*
* pjr    04.08.89    Added output to file capability. This can be compiled 
*                       in by defining the H_FILEIO flag. Note that you also 
*                       have to have a file open with an fd of lfp, although 
*                       this can be changed by changing the decn below.
*
**************************************************************************/
#include <stdio.h>
#include "hexprint.h"

#ifdef H_FILEIO
extern FILE *lfp;
#else
#define lfp stdout
#endif /* H_FILEIO */

#ifdef H_COMPRESS
int hex_compression = FALSE;    /* compression is off as a default */
#endif /* H_COMPRESS */

#ifdef H_OFFSETS
int offset_print = FALSE;    /* only print offsets on request */
long offset = 0L;        /* default start offset for printing */
#endif /* H_OFFSET */

/*
 * hexprint
 *
 * routine to print a buffer out in hex form with ascii form on
 * the right hand side
 */
/**************************************************************************/
void hexprint(buf, buflen)
/**************************************************************************/
char *buf;    /* ptr to data part of msg req, protocol format, to print */
int buflen;
{
int i,j;
char string[H_SLEN];

#ifdef H_COMPRESS
int done_compression = FALSE;    /* have we done any compression ? */
char o_string[H_SLEN];        /* string prior to the current one */
#endif /* H_COMPRESS */

#ifdef H_OFFSETS
long o;
    if (offset_print)
    {
        o = offset;
        fprintf(lfp,"%5x  ",o);
    }
#endif /* H_OFFSETS */

    for (i=0; i<buflen; i++) {
        string[i%H_SLEN] = *buf++;
        if (i%H_SLEN == (H_SLEN-1)) {
#ifdef H_OFFSETS
            o += H_SLEN;
#endif /* H_OFFSETS */
#ifdef H_COMPRESS
            if (hex_compression)
                if (i == (H_SLEN-1)) /* first time around ? */
                    BCOPY(string, o_string, H_SLEN);
                else
                {

                if (BCMP(o_string, string, H_SLEN) == 0)
                    {
                        fprintf(lfp,"* ");
                        done_compression = TRUE;
                        BCOPY(string, o_string, H_SLEN);
                        continue;
                    }
                    else if (done_compression)
                    {
                        fprintf(lfp,"\n");
#ifdef H_OFFSETS
                        if (offset_print)
                            fprintf(lfp, "%5x  ",o - H_SLEN);
#endif /* H_OFFSETS */
                        done_compression = FALSE;
                    }
                    BCOPY(string, o_string, H_SLEN);
                }
#endif /* H_COMPRESS */
            for (j=0; j<H_SLEN; j++)
                fprintf(lfp, "%2x ",(unsigned char)string[j]);

            for (j=0; j<H_SLEN; j++)
                if (string[j] >= 0x20 && string[j] <= 0x7e)
                    fprintf(lfp, "%c",string[j]);
                else
                    fprintf(lfp, ".");
            fprintf(lfp, "\n");
#ifdef H_OFFSETS
            if ((i != (buflen -1)) && offset_print)
                fprintf(lfp, "%5x  ",o);
#endif /* H_OFFSETS */
        } else
            if ((i%H_SLEN < (H_SLEN-1)) && (i == buflen-1)) {
#ifdef H_COMPRESS
                if (done_compression)
                {
                    fprintf(lfp, "\n");
#ifdef H_OFFSETS
                    if (offset_print)
                        fprintf(lfp, "%5x  ",o);
#endif /* H_OFFSETS */
                    done_compression = FALSE;
                }
                BCOPY(string, o_string, H_SLEN);
#endif /* H_COMPRESS */
                for (j=0; j<=(i%H_SLEN); j++)
                    fprintf(lfp, "%2x ",(unsigned char)string[j]);

                for (j=0; j<((H_SLEN-1)-(i%H_SLEN)); j++)
                    fprintf(lfp, "   ");

                for (j=0; j<=(i%H_SLEN); j++)
                    if (string[j] >= 0x20 &&
                        string[j] <= 0x7e)
                        fprintf(lfp, "%c",string[j]);
                    else
                        fprintf(lfp, ".");

                fprintf(lfp, "\n");
            }
    } /* end of for */

#ifdef H_COMPRESS
    if (done_compression)
        fprintf(lfp, "\n");
#endif /* H_COMPRESS */

} /* end of hexprint */

