/*
 * this file is a part of yabbs - yet another bulletin board system.
 * Copyright (C) 1993, 1994 Alex Wetmore.  
 * email: alex@phred.org
 * address: 6 rech ave
 *          oreland pa 19075
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdio.h>

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE -1
#endif

void putprint(char *st) {
    char i;

    for (i = 0; i < 16; i++) {
        if ((st[i] >= 32) && (st[i] <= 126)) {
            putchar(st[i]);
        } else {
            putchar('.');
        }
    }
}

int main(int argc, char **argv) {
    int     l,                                      /* current line         */
            i,                                      /* counter              */
            c,                                      /* input character      */
            nc,                                     /* next character       */
            sl = 23,                                /* screen length        */
            help = FALSE,                           /* show usage flag      */
            banner = TRUE;                          /* show banner          */
    char    st[17],                                 /* current line         */
            *file = NULL;                           /* file to read from    */
    FILE    *fi;                                    /* file descriptor      */

    /*
     * read command line arguments
     */
    if (argc == 1) {
        fi = stdin;
    } else {
        for (i = 1; i < argc; i++) {
            if (argv[i][0] == '-') {                /* optional switch      */
                switch (argv[i][1]) {
                    case 'l':                       /* screen length        */
                        if (strlen(argv[i]) == 2) { /* space after l        */
                            sl = atoi(argv[++i]);   /*   sl is next parm    */
                        } else {                    /* no space after l     */
                            sl = atoi(&argv[i][2]); /*   sl is this parm    */
                        }
                        break;
                    case 'n':                       /* no banner            */
                        banner = FALSE;
                        break;
                    default :                       /* invalid option       */
                        help = TRUE;
                }
            } else {                                /* filename to read     */
                file = argv[i];
            }
        }

        /*
         * if user picked an invalid option display a help screen
         */
        if (help) {
            printf("usage: %s [-l#] [-n] [<file>]\n", argv[0]);
            printf("  %s shows a split hex/ascii dump of a file\n");
            printf("  -l #   shows banner every # lines (default = 23)\n");
            printf("  -n     no banner (defaults to banner)\n");
            printf("  <file> the file to dump (default = stdin)\n");
            return(-1);
        }
    
        /*
         * open the input file
         */
        if (file == NULL) {                         /* no file, used stdin  */
            fi = stdin;
            strcpy(file, "stdin");
        } else {                                    /* open users file      */
            if ((fi = fopen(file, "rb")) == NULL) {
                printf("%s: error opening %s for read\n", argv[0], file);
                return(-1);
            }
            file[13] = 0;
        }
    }

    /* 
     * reset counters, show banner if they want it
     */
    i = l = 0;
    if (banner) {
        printf("%-13s 0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F\n",
            file);
    }
    printf("%05d,%05x: ", l * 16, l * 16);

    /*
     * we have to have a latency of one character, so that we don't get
     * any junk at the end of the file.  so we read nc, and work with c
     */
    nc = getc(fi);

    /*
     * loop till end of file
     */
    while (!feof(fi)) {
        /* read a character from the file and update st and i               */
        c = nc; nc = getc(fi); st[i] = c; st[i + 1] = 0; i++;

        printf("%02x ", c);                     /* display our character    */
        if (i == 8) printf(" ");                /* extra space between 7&8  */
        if (i == 16) {                          /* next line at 16          */
            l++; i = 0;                         /*   reset our counters     */
            printf("  "); 
            putprint(st); printf("\n");         /* show st (ascii chars)    */
            if (((l % sl) == 0) && (banner))    /* show banner if needed    */
                printf(
                    "%-13s 0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F\n",
                    file);
            printf("%05d,%05x: ", l * 16, l * 16);  /* goto next line       */
        }
    }

    /* 
     * we are done with file.  Fix up this line and exit
     */
    if (i != 0) {                               /* not done with line       */
        if (i < 8) printf(" ");                 /* pad out our extra spaces */
        for (; i < 16; i++) {                   /*  plus one more if we are */
            printf("   ");                      /*  before column 8         */
            st[i] = ' ';
        }
        printf("  "); putprint(st); printf("\n");   /* print ascii chars    */
    } else {                                    /* done with line           */
        printf("\r            \r");             /* get rid of numbers       */
    }
}
