2
\$\begingroup\$

I made this hex dump after being dissatisfied with the free hexdumps out there. The biggest dissatisfaction is that the encodings for the char bytes were not color encoded, just like the hexyl hexdump program.

If you are interested in reading the full background story, you may click on the Medium link: https://medium.com/@tanveerasalim/my-new-colorful-hex-dump-command-a114a043b61c

I tested this hexdump on macOS, Linux, and Windows (CYGWIN) before posting here.

I plan to transform this hex dump into an actual vim-like hex editor, since I could not find a preexisting one of the like of it either.

Instructions For Use:

NAME

tscd

SYNOPSIS

tscd [options] [infile [outfile]]

DESCRIPTION

tscd can create a hexadecimal, decimal, binary, or octal dump of any file. The numerical values will be displayed in a table.To the rightmost of each row will be the ASCII characters corresponding to the ASCII codes in the table.

COLOR ENCODINGS

Below is the Color Encoding Scheme (ASCII):

Red: Non-printable ASCII characters

Orange: Printable (Alphabetic) Characters

Yellow: Base 10 Numerical Digits

Green: ASCII Whitespace Characters

Purple: Punctuation Characters

Gray: NUL byte (00)

OPTIONS

-b Binary dump specified. Each character in file will be translated into its binary number form and displayed in the table.

-c Specify number of columns per row in ASCII code table.

-d Decimal Dump specified. Each character in file will be translated into its binary number form and displayed in the table.

-o Octal Dump specified. Each character in file will be translated into its octal number form and displayed in the table.

-p Print view specified. tscd will simply print the contents of the file directly intointo stdout.

Questions:

  1. Would you actually prefer to use this compared to all other free command-line hexdumps out there, not counting GUI-based ones?

  2. Are you interested in me transforming this program into a vim-like color-encoded hex editor program?

  3. Are you also confident the implementation is portable across Windows (such as on CYGWIN), macOS, and Linux systems?

Implementation:

The link to the GitHub Repository page is: https://github.com/tanveerasalim/TSCD

The complete implementation of the hex dump is below:

#if 0
NOTICE: All the software in this repository

comes with absolutely

NO WARRANTY and provided "as is" basis.

Copyright (C) Tanveer Salim 2018-INFINITY

This software and all other software in

this repository is distributed with a GNU GPL

License v2.0. All are free to copy, share, 


distribute, and/or modify this software,

even commercially as long as it compliant

with GNU GPL v2.0 LICENSING terms as well

as the terms of this copyright and license

statement.

All software that was inspired

or is a derivative of this work must have

the exact same LICENSE and copyright permissions.

#endif

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#ifndef __rsize_t_defined
typedef size_t rsize_t;
#define __rsize_t_defined 1
#endif

#ifdef __RSIZE_MAX__
#define RSIZE_MAX (__RSIZE_MAX__)
#else

#define RSIZE_MAX ( (SIZE_MAX ) >> ( 1 ) )
#endif


#ifndef __uint8_t_defined
typedef unsigned char uint8_t;
#define __uint8_t_defined 1
#endif

#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
#define __uint32_t_defined 1
#endif

#if 0

Bug: When Number of characters in row

is equal to NUM_HEX_ROWS, the last f

in 0xff is deleted and replaced with

a period.

Bug: Number of columns == Number of bytes per row!

NUM_HEX_ROWS == (desired number of columns)/2

default number of columns: 16 to make 16 bytes displayed in total per row

So:

NUM_HEX_ROWS == Number of desired columns

Simple! :D
#endif
//#define NUM_HEX_ROWS_ORIGINAL 16

rsize_t NUM_HEX_ROWS = 16;

rsize_t NUM_BIN_ROWS = 6;

rsize_t NUM_OCT_ROWS = 12;

rsize_t NUM_DEC_ROWS = 12;

rsize_t UTF8_HEX_ROWS = 6;

_Bool bintable_request = 0;

_Bool octtable_request = 0;

_Bool dectable_request = 0;


void colorchar(uint8_t c)
{

        if ( c == 0x0 )
        {
            printf("\e[38;5;244m");
        }

        else if ( isalpha(c) )
        {

            printf("\e[38;5;208m");


        }

        else if ( isdigit(c) )
        {
            printf("\e[38;5;226m");
        }   

        else if ( !isprint(c) )
        {
            printf("\e[38;5;196m");
        }

        else if ( isspace(c) )
        {
            printf("\e[38;5;40m");
        }

        else if ( ispunct(c) )
        {
//          printf("\e[38;5;164m");

            printf("\e[38;5;201m");
        }

        else if ( c < 16 )
        {
            printf("\e[0;32m");
        }

        else if ( c >= 16 && c <= 31 )
        {
            printf("\e[1;35m");
        }

}

void resetcolor(void)
{
    printf("\033[0m");
}

_Bool isutf8cntrl(uint32_t c)
{


}

void colorutf8(uint8_t * s)
{
    uint32_t utf8_hex = 0x00;

    uint8_t * s_p = s;

    while ( *s_p != 0x00 )
    {
        utf8_hex += *s_p;

        utf8_hex <<= 8;

        s_p++;
    }

}

void printview(FILE * in, FILE * out,const rsize_t FILE_SIZE)
{
    rsize_t i = 0;

    uint8_t c = 0;

    while ( i < FILE_SIZE )
    {
        c = fgetc(in);

        if ( out != stdout )
        {   
            fprintf(out,"%c",c);
        }

        else
        {
            colorchar(c);
            printf("%c",c);
            resetcolor();
        }


        i++;
    }

}
void reverse(unsigned char s[])
{
  for (int i = 0, j = strlen(s)-1; i < j; i++, j--)
  {
    unsigned char temp = s[i];

    s[i] = s[j];

    s[j] = temp;
  }
}

unsigned char * print_binary(unsigned char input)
{


  static unsigned char s[10];

  unsigned char * s_p = &s[0];

  while (input > 0)
  {
    *s_p++ = (unsigned char)((input&1)+'0');

    input >>= 1;
  }

  *s_p = '\0';

  reverse(s);

  return s;

}



void print_bintable2(FILE * in, FILE * out, unsigned char ASCII[], const rsize_t FILE_SIZE)
{
    rsize_t i = 0;

    rsize_t u = 0;

    unsigned long fpos = 0;

    rsize_t j = 0; //need this to create printable ASCII in output

    unsigned char c = 0;

    while ( i < FILE_SIZE )
    {
        c = fgetc(in);

#if 0

This printf actually forces printing of ASCII.

#endif  
        if ( i == 0 )
        { colorchar(c); fprintf(out,"%08x:%c",i,0x20); resetcolor(); }

        else if ( (i%NUM_BIN_ROWS) == 0  )
        {
                fputc(0x20,out);

                if ( i >= NUM_BIN_ROWS )
                {   

                    fseek(in,-NUM_BIN_ROWS-1,SEEK_CUR);

                }

                else
                {
                    fseek(in,0,SEEK_SET);   
                }

                u = 0;              

                while ( 

                    u < NUM_BIN_ROWS


                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                c = fgetc(in); //catch up to latest row


                colorchar(c);

                fprintf(out,"\n%08x:%c",i,0x20);

                resetcolor();   
        }

        colorchar(c);

        fprintf(out,"%08s%c",print_binary(c),0x20);

        resetcolor();

#if 0   
        (i%2 == 0) ? ( fprintf(out,"%08s",print_binary(c)) ) : ( fprintf(out,"%08s%c",print_binary(c),0x20) );

#endif      
        i++;    


        // Bug: Write code to place ff and extra spaces to align last ASCII line here
    }

        if ( i == FILE_SIZE )
        {
            rsize_t index = i;

            while ( index % NUM_BIN_ROWS != 0 ) 
            {


                (index%2 == 0) 

                    ? 

                    ( fprintf(out,"%*c",0x9,0x20) ) 

                    : 

                    ( fprintf(out,"%*c",0x9,0x20) );

                index++;
            }
#if 0

This while loop is meant for

a line that is equal to

NUM_BIN_ROWS

#endif  

            if ( index % NUM_BIN_ROWS == 0 )
            {
                fputc(0x20,out);
            }   

        }



    if ( i == FILE_SIZE && (i%NUM_BIN_ROWS) != 0  )
    {

                rsize_t space_align = i;

                fpos = ftell(in);

                fseek(in,-(i%NUM_BIN_ROWS),SEEK_CUR);

                u = 0;              

                while ( 

                    u < ( i%NUM_BIN_ROWS )

                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);   

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                fseek(in,fpos,SEEK_SET);

    }

    else // ( i == FILE_SIZE && (i%NUM_BIN_ROWS) == 0  )
    {

                rsize_t space_align = i;

                fpos = ftell(in);

                fseek(in,-(NUM_BIN_ROWS),SEEK_CUR);

                u = 0;              

                while ( 

                    u < ( NUM_BIN_ROWS )

                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                fseek(in,fpos,SEEK_SET);

    }

}

void print_dectable(FILE * in, FILE * out, unsigned char ASCII[], const rsize_t FILE_SIZE)
{
    rsize_t i = 0;

    rsize_t u = 0;

    unsigned long fpos = 0;

    rsize_t j = 0; //need this to create printable ASCII in output

    unsigned char c = 0;

    while ( i < FILE_SIZE )
    {
        c = fgetc(in);

        colorchar(c);   
#if 0

This printf actually forces printing of ASCII.

#endif  

        if ( i == 0 )
        { fprintf(out,"%08x:%c",i,0x20); }


        else if ( (i%NUM_DEC_ROWS) == 0  )
        {
                fputc(0x20,out);

                fputc(0x20,out);

                if ( i >= NUM_DEC_ROWS )
                {   

                    fseek(in,-NUM_DEC_ROWS-1,SEEK_CUR);

                }

                else
                {
                    fseek(in,0,SEEK_SET);   
                }

                u = 0;              

                while ( 

                    u < NUM_DEC_ROWS


                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                c = fgetc(in); //catch up to latest row

                colorchar(c);

                fprintf(out,"\n%08x:%c",i,0x20);

                resetcolor();   
        }

        colorchar(c);


        (i%1 != 0) ? ( fprintf(out,"%03u",c) ) : ( fprintf(out,"%c%03u",0x20,c) );

        i++;    

        resetcolor();

        // Bug: Write code to place ff and extra spaces to align last ASCII line here
    }

        if ( i == FILE_SIZE )
        {
            rsize_t index = i;

            while ( index % NUM_DEC_ROWS != 0 ) 
            {


                (index%2 == 0) 

                    ? 

                    ( fprintf(out,"%c%c%c%c",0x20,0x20,0x20,0x20) ) 

                    : 

                    ( fprintf(out,"%c%c%c%c",0x20,0x20,0x20,0x20) );

                index++;
            }
#if 0

This while loop is meant for

a line that is equal to

NUM_DEC_ROWS

#endif  

            if ( index % NUM_DEC_ROWS == 0 )
            {
                fputc(0x20,out);
            }   

        }



    if ( i == FILE_SIZE && (i%NUM_DEC_ROWS) != 0  )
    {
                fputc(0x20,out);

                rsize_t space_align = i;

                fpos = ftell(in);

                fseek(in,-(i%NUM_DEC_ROWS),SEEK_CUR);

                u = 0;              

                while ( 

                    u < ( i%NUM_DEC_ROWS )

                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                fseek(in,fpos,SEEK_SET);

    }

    else // ( i == FILE_SIZE && (i%NUM_DEC_ROWS) == 0  )
    {
                fputc(0x20,out);

                rsize_t space_align = i;

                fpos = ftell(in);

                fseek(in,-(NUM_DEC_ROWS),SEEK_CUR);

                u = 0;              

                while ( 

                    u < ( NUM_DEC_ROWS )

                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                fseek(in,fpos,SEEK_SET);

    }

}

void print_octtable(FILE * in, FILE * out, unsigned char ASCII[], const rsize_t FILE_SIZE)
{
    rsize_t i = 0;

    rsize_t u = 0;

    unsigned long fpos = 0;

    rsize_t j = 0; //need this to create printable ASCII in output

    unsigned char c = 0;

    while ( i < FILE_SIZE )
    {
        c = fgetc(in);

        colorchar(c);   
#if 0

This printf actually forces printing of ASCII.

#endif  

        if ( i == 0 )
        { fprintf(out,"%08x:%c",i,0x20); }


        else if ( (i%NUM_OCT_ROWS) == 0  )
        {
                fputc(0x20,out);

                fputc(0x20,out);

                if ( i >= NUM_OCT_ROWS )
                {   

                    fseek(in,-NUM_OCT_ROWS-1,SEEK_CUR);

                }

                else
                {
                    fseek(in,0,SEEK_SET);   
                }

                u = 0;              

                while ( 

                    u < NUM_OCT_ROWS


                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                c = fgetc(in); //catch up to latest row

                colorchar(c);

                fprintf(out,"\n%08x:%c",i,0x20);

                resetcolor();   
        }

        colorchar(c);


        (i%1 != 0) ? ( fprintf(out,"%03o",c) ) : ( fprintf(out,"%c%03o",0x20,c) );

        i++;    

        resetcolor();

        // Bug: Write code to place ff and extra spaces to align last ASCII line here
    }

        if ( i == FILE_SIZE )
        {

            rsize_t index = i;

            while ( index % NUM_OCT_ROWS != 0 ) 
            {


                (index%2 == 0) 

                    ? 

                    ( fprintf(out,"%c%c%c%c",0x20,0x20,0x20,0x20) ) 

                    : 

                    ( fprintf(out,"%c%c%c%c",0x20,0x20,0x20,0x20) );

                index++;
            }
#if 0

This while loop is meant for

a line that is equal to

NUM_OCT_ROWS

#endif  

            if ( index % NUM_OCT_ROWS == 0 )
            {
                fputc(0x20,out);

            }   

        }



    if ( i == FILE_SIZE && (i%NUM_OCT_ROWS) != 0  )
    {
                fputc(0x20,out);

                rsize_t space_align = i;

                fpos = ftell(in);

                fseek(in,-(i%NUM_OCT_ROWS),SEEK_CUR);

                u = 0;              

                while ( 

                    u < ( i%NUM_OCT_ROWS )

                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                fseek(in,fpos,SEEK_SET);

    }

    else // ( i == FILE_SIZE && (i%NUM_OCT_ROWS) == 0  )
    {
                fputc(0x20,out);

                rsize_t space_align = i;

                fpos = ftell(in);

                fseek(in,-(NUM_OCT_ROWS),SEEK_CUR);

                u = 0;              

                while ( 

                    u < ( NUM_OCT_ROWS )

                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                fseek(in,fpos,SEEK_SET);

    }

}


#if 0
For is_utf8cont, assume correct UTF-8 encoding
#endif

#if 0
_Bool is_utf8cont(uint8_t c)
{

//First try to disprove by detecting starting byte

    if ( ( c >> 3 ) == 0b11110 )
    {
        return 0;   
    }

    else if ( ( c >> 4 ) == 0b1110 )
    {
        return 0;
    }

    else if ( ( c >> 5 ) == 0b110 )
    {
        return 0;
    }

    else if ( ( c >> 7 ) == 0b0 )
    {
        return 0;
    }

    return 1;

}
#endif

#if 0
void print_utf8hextable(FILE * in, FILE * out,const rsize_t FILE_SIZE)
{
    rsize_t i = 0;

    rsize_t utf8i = 0; //for printing actual UTF8 character

    static uint32_t utf8_hex = 0x00;

    const rsize_t UTF8_STR_SIZE = UTF8_HEX_ROWS*4*sizeof(uint8_t)+1;

    static uint8_t utf8_str[UTF8_HEX_ROWS*4*sizeof(uint8_t)+1];

    memset_s(utf8_str,UTF8_STR_SIZE,0x00,UTF8_STR_SIZE);

    static uint8_t c = 0;

    static long utf8_offsets[UTF8_HEX_ROWS];

    static long * utf8op; 

    utf8op = utf8_offsets;

    rsize_t cur_utf8char = 0;

    while ( i < FILE_SIZE )
    {
        c = fgetc(in);

#if 0
Print actual hexadecimal representation of UTF-8

character
#endif
        if ( i == 0 )
        {
            printf("%.08x: ",i);

        }

        else if ( !is_utf8cont(c) ) //starting byte for UTF-8 character
        {
            printf("%.08x ",utf8_hex);

            utf8_hex = 0x00;

            *utf8op = ftell(in);


        }

        else
        {
            utf8_hex += c;

            utf8_hex <<= 8;

            utf8_hex &= 0xffffff00  

        }

        if ( utf8i == UTF8_HEX_ROWS )
        {
            cur_utf8char = ftell(in);

            utf8op = utf8_offsets;

            rsize_t ic = 0;

            while ( utf8op < (utf8_offsets + UTF8_HEX_ROWS) )
            {
                fseek(in,*utf8op,SEEK_BEG);     

                while (ic > 0 && !is_utf8cont(c) )
                {               
                    c = fgetc(in);

                    fputc(c,out);

                    ic++;
                }

                utf8op++;

                ic = 0;
            }   

            memset_s(utf8_offsets,UTF8_HEX_ROWS*sizeof(uint8_t),0x00,UTF8_HEX_ROWS*sizeof(uint8_t));    

            fseek(in,cur_utf8char,SEEK_BEG);

            utf8i = 0;

            printf("\n%.08x: ",i);
        }

        else
        {
            utf8i++;    
        }   

        i++;

    }   
}
#endif

void print_hextable(FILE * in, FILE * out, unsigned char ASCII[], const rsize_t FILE_SIZE)
{
    rsize_t i = 0;

    rsize_t u = 0;

    unsigned long fpos = 0;

    rsize_t j = 0; //need this to create printable ASCII in output

    unsigned char c = 0;

    while ( i < FILE_SIZE )
    {
        c = fgetc(in);

        colorchar(c);   
#if 0

This printf actually forces printing of ASCII.

#endif  

        if ( i == 0 )
        { fprintf(out,"%08x:%c",i,0x20); }


        else if ( (i%NUM_HEX_ROWS) == 0  )
        {
                fputc(0x20,out);

                fputc(0x20,out);

                if ( i >= NUM_HEX_ROWS )
                {   

                    fseek(in,-NUM_HEX_ROWS-1,SEEK_CUR);

                }

                else
                {
                    fseek(in,0,SEEK_SET);   
                }

                u = 0;              

                while ( 

                    u < NUM_HEX_ROWS


                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                c = fgetc(in); //catch up to latest row

                colorchar(c);

                fprintf(out,"\n%08x:%c",i,0x20);

                resetcolor();   
        }

        colorchar(c);


        (i%1 != 0) ? ( fprintf(out,"%02x",c) ) : ( fprintf(out,"%c%02x",0x20,c) );

        i++;    

        resetcolor();

        // Bug: Write code to place ff and extra spaces to align last ASCII line here
    }

        if ( i == FILE_SIZE )
        {
            rsize_t index = i;

            while ( index % NUM_HEX_ROWS != 0 ) 
            {


                (index%2 == 0) 

                    ? 

                    ( fprintf(out,"%c%c%c",0x20,0x20,0x20) ) 

                    : 

                    ( fprintf(out,"%c%c%c",0x20,0x20,0x20) );

                index++;
            }
#if 0

This while loop is meant for

a line that is equal to

NUM_HEX_ROWS

#endif  

            if ( index % NUM_HEX_ROWS == 0 )
            {
                fputc(0x20,out);

                fputc(0x20,out);


            }   

        }


    if ( i == FILE_SIZE && (i%NUM_HEX_ROWS) != 0  )
    {

                rsize_t space_align = i;

                fpos = ftell(in);

                fseek(in,-(i%NUM_HEX_ROWS),SEEK_CUR);

                u = 0;              

                while ( 

                    u < ( i%NUM_HEX_ROWS )

                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                fseek(in,fpos,SEEK_SET);

    }

    else // ( i == FILE_SIZE && (i%NUM_HEX_ROWS) == 0  )
    {

                rsize_t space_align = i;

                fpos = ftell(in);

                fseek(in,-(NUM_HEX_ROWS),SEEK_CUR);

                u = 0;              

                while ( 

                    u < ( NUM_HEX_ROWS )

                      )
                {
                    ( c = fgetc(in) );  

                    colorchar(c);

                    if ( isprint(c) )
                    {   
                        fputc(c,out);
                    }

                    else
                    {
                        fprintf(out,"\u00b7");
                    }

                    u++;

                    resetcolor();
                }

                fseek(in,fpos,SEEK_SET);

    }

}

#if 0
Last argument, argument index

argc-1, must have filename
#endif

int main(int argc, char ** argv)
{

    FILE * in = NULL;

    FILE * out = stdout;

    if ( argc < 2 )
    {
        fprintf(in,"%llu: Less than two arguments!\n",__LINE__);

        return 1;
    }

    if ( ( (argc-2) > 0 ) && ( ( in = fopen(argv[argc-2],"rb") ) != NULL ) )
    {
        if ( ( out = fopen(argv[argc-1],"wb+") ) == NULL )
        {
            fprintf(stderr,"\033[1;31m\n\0");   

            fprintf(stdout,"%llu: Failed to write to file %s!\n",__LINE__,argv[argc-1]);

            fprintf(stderr,"\033[0m\n\0");

            return 1;
        }


    }

    else if ( ( in = fopen(argv[argc-1],"rb") ) == NULL )
    {
        fprintf(stderr,"\033[1;31m\n\0");   

        fprintf(stdout,"%llu: Failed to open file!\n",__LINE__);

        fprintf(stderr,"\033[0m\n\0");

        return 1;
    }

    fseek(in,0L,SEEK_END);

    const rsize_t SIZE = ftell(in);

    static unsigned char * ascii_line; 

    ascii_line = (unsigned char *)calloc(NUM_HEX_ROWS+1,sizeof(unsigned char));

    rewind(in);

    while ( *++argv != NULL && **argv == 0x2d )
    {
        switch ( *++(*argv)  )
        {

            case 0x63:
                {
                    // get column number

                    char const * column_num = *++argv; 

                    while ( isdigit( *(*argv) ) != 0 )
                    {   (*argv)++;  }

                    if ( **argv != 0x0 )
                    {

                        fprintf(stderr,"\033[1;31m\n\0");   

                        fprintf(stderr,"%llu: Error! Column"
                                " argument is not a" 
                                " type of unsigned"
                                " integer!\n",
                                __LINE__
                               );

                        fprintf(stderr,"\033[0m\n\0");

                        return 1;
                    }



                    NUM_HEX_ROWS = (rsize_t)strtol(column_num,NULL,10);

                    free(ascii_line);

                    ascii_line = (unsigned char *)calloc(NUM_HEX_ROWS,sizeof(unsigned char));

                    NUM_BIN_ROWS = (rsize_t)strtol(column_num,NULL,10);

                    NUM_OCT_ROWS = (rsize_t)strtol(column_num,NULL,10);

                    NUM_DEC_ROWS = (rsize_t)strtol(column_num,NULL,10);

                    break;
                }

            case 0x62:
                {
                    bintable_request = 1;   

                    free(ascii_line);

                    ascii_line = (unsigned char *)calloc(NUM_BIN_ROWS+1,sizeof(unsigned char));

                    break;
                }

            case 0x64:
                {
                    dectable_request = 1;

                    free(ascii_line);                   
                    ascii_line = (unsigned char *)calloc(NUM_DEC_ROWS+1,sizeof(unsigned char));

                    break;
                }

            case 0x6f: 
                {
                    octtable_request = 1;   

                    free(ascii_line);

                    ascii_line = (unsigned char *)calloc(NUM_OCT_ROWS+1,sizeof(unsigned char));

                    break;
                }   

            case 0x70:
                {
                    printview(in,out,SIZE);

                    return 0;

                }




            default:
                {
                    break;
                }
        }   

    }

    if ( dectable_request == 1 )
    {
        print_dectable(in,out,ascii_line,SIZE);
    }

    else if ( octtable_request == 1 )
    {
        print_octtable(in,out,ascii_line,SIZE);
    }   

    else if ( bintable_request == 1 )
    { 
        print_bintable2(in,out,ascii_line,SIZE);
    }

    else
    {
        print_hextable(in,out,ascii_line,SIZE);
    }

    if ( fclose(in) == EOF )
    {
        fprintf(stderr,"\033[1;31m\n\0");   

        fprintf(stderr,"%llu: Error! Failed to close %s\n",__LINE__,argv[argc-1]);

        fprintf(stderr,"\033[0m\n\0");

        return 1;
    }

    if ( fclose(out) == EOF )
    {
        fprintf(stderr,"\033[1;31m\n\0");   

        fprintf(stderr,"%llu: Error! Failed to close %s\n",__LINE__,argv[argc-1]);

        fprintf(stderr,"\033[0m\n\0");

        return 1;
    }


    return 0;
}

SHA256SUM: 592e94e830a99919e89f76e313513e5d87aee948c8bc7a324ef834c51e634e60 *tscd6.c

\$\endgroup\$
1
  • 3
    \$\begingroup\$ This code would be way more readable without most of the blank lines. \$\endgroup\$ Commented Apr 27, 2019 at 0:16

1 Answer 1

3
\$\begingroup\$

Don't write prose in #if 0 sections. The following won't work:

#if 0
don't do this
#endif

The C preprocessor still has to parse the lines, and unbalanced single and double quotes will lead to syntax errors or at least warnings. No one else does this, and for good reason.


Regarding the license statement: forget it. Any code that is posted on this site is covered by a Creative Commons license, no matter what you write inside your code.

You probably made up the license terms in your code, since I never saw this wording anywhere else. If you want your software to be reused, stick to the standard license terms. Otherwise people will not use your code because they are afraid of not knowing what exactly you mean by your terms.


Do not mess around with any identifiers starting with __. For rsize_t and uint8_t, just assume they are defined. It's pretty easy to pass a -Drsize_t=size_t command line option for the very few systems that don't support these types.


All global variables that are only used in your translation unit should be declared static. So instead of:

rsize_t NUM_HEX_ROWS = 16;

better write:

static rsize_t NUM_HEX_ROWS = 16;

This will make this variable invisible for code outside of this translation unit, which is good. If any other file in the whole project also defines its NUM_HEX_ROWS variable, your code should not be influenced by that.

The same goes for functions such as colorchar. These should also be declared static.


Instead of using _Bool, you should rather #include <stdbool.h> and use bool. This header is available since C99, which is 20 years old by now. You can just assume it exists. Everyone who is using older compilers will already know how to make your code work with their compiler.


In colorchar, using the \e escape sequence is not portable. Better use \x1B instead. You could also define a function to print a colored character:

static void putchar_colored(uint8_t ch, int color)
{
    printf("\x1B[38;5;%dm%c\x1B[0m", color, ch);
}

...
putchar_colored('x', 244);

The function isutf8cntrl never returns a value. That's undefined behavior. Remove that function, or fix it.

All function names starting with is followed by a lowercase letter are reserved by the C standard for future extensions. You should name your function is_utf8_control instead.


Instead of:

void colorutf8(uint8_t * s)

the parameter s should point to constant memory, since this function never modifies it:

void colorutf8(const uint8_t * s)

I have no idea what the purpose of that function is. Converting a string to a number has nothing to do with UTF-8. Furthermore the function is unused. Remove it.


Next time, before posting any code here, let your IDE or your editor format the code properly. This means:

  • an empty line between functions
  • no excessive empty lines between your lines of code, especially in print_bintable2. There's no point in inserting an empty line after every line of code. Empty lines have a meaning, it's like a paragraph in written prose.

I don't understand this code:

        while (

                u < NUM_BIN_ROWS


                )

That's a mess. There is no point of having this much whitespace in your code. Rewrite it as:

        while (u < NUM_BIN_ROWS)

if (i % 1 != 0) {

This condition always evaluates to true.

if (index % 2 == 0) {
    fprintf(out, "%c%c%c", 0x20, 0x20, 0x20);
} else {
    fprintf(out, "%c%c%c", 0x20, 0x20, 0x20);
}

There's no point in having an if statement in which the then and the else branch have identical code.


The code in print_dectable looks structurally similar to the code in print_bintable2. You should look for the common parts yourself and try to merge them into one function. It's probably a good idea to have functions called dump_line_dec and dump_line_hex, since the rest of the code is probably the same.

As a guideline, none of your functions should ever be longer than 50 lines. If the whole text of a function doesn't fit on a single screen, it's too large and can probably be split into at least two separate functions.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.