/*
**  PROGRAM TO VERIFY THE CHECKSUMS OF AN HP 2100 RELOCATABLE BINARY TAPE
*/
#include <stdio.h>

main (int argc, char **argv) {

    FILE *fp;
    int done, ii, jj, kk, nn, cksum, count, dummy, maxnull, accum, nbchecked;
    int ident, addr, reloc, ri, data, data2;
    int r[256];
    int list=0;

    jj=1;
    for (ii=1; ii<argc; ii++) {
        if (!strcmp(argv[ii],"-l")) list=1;
        else argv[jj++]=argv[ii];
    }
    argc=jj;

    if (argc != 2) {
        printf ("Usage: chkrel options filename\n");
        printf ("\n");
        printf ("Options are:  -l  symbol listing to stdout\n");
        exit (-1);
    }
    fp = fopen (argv[1], "rb");
    if (!fp) {
        printf ("Can't open file %s\n", argv[1]);
        exit (-1);
    }
    nbchecked = 0;
    maxnull = 10000;
    done = 0;
    while (!done) {
        count = fgetc (fp);
        if (count == EOF) {
            printf ("Unexpected EOF!\n");
            done = 1;
        } else if (!count) {
            maxnull--;
            if (!maxnull) done=1;
        } else {
            maxnull = 100;
            dummy = fgetc (fp);
            for (ii=1; ii<count; ii++) {
                r[ii] = (fgetc(fp) << 8) | fgetc(fp);
            }
            accum = r[1];
            cksum = r[2];
            for (ii=3; ii<count; ii++) {
                accum = accum + r[ii];
                nbchecked++;
            }
            if (accum != cksum) {
                printf ("Checksum Error!\n");
                done = 1;
            } else {
                ident = (r[1] >> 13) & 7;
                /*  printf ("count=%d, ident=%d\n", count, ident);  */
                if (ident==1) {
                    /*
                    **  NAM record
                    */
                    ii = 3;
                    printf ("NAM %c%c%c%c%c %06o %06o %06o\n",
                             (r[ii] >> 8) & 0x7F ,
                              r[ii] & 0x7F ,
                             (r[ii+1] >> 8) & 0x7F ,
                              r[ii+1] & 0x7F ,
                             (r[ii+2] >> 8) & 0x7F ,
                              r[ii+3] , r[ii+4] , r[ii+5] );
                } else if (ident==2) {
                    /*
                    **  ENT record
                    */
                    ii = 3;
                    while (ii < count) {
                        printf ("ENT %c%c%c%c%c %06o\n",
                                 (r[ii] >> 8) & 0x7F ,
                                  r[ii] & 0x7F ,
                                 (r[ii+1] >> 8) & 0x7F ,
                                  r[ii+1] & 0x7F ,
                                 (r[ii+2] >> 8) & 0x7F ,
                                  r[ii+3] );
                        ii += 4;
                    }
                } else if (ident==4) {
                    /*
                    **  EXT record
                    */
                    ii = 3;
                    printf ("EXT ");
                    while (ii < count) {
                        if ( !(ii % 33) ) printf ("\n    ");
                        printf ("%c%c%c%c%c ",
                                 (r[ii] >> 8) & 0x7F ,
                                  r[ii] & 0x7F ,
                                 (r[ii+1] >> 8) & 0x7F ,
                                  r[ii+1] & 0x7F ,
                                 (r[ii+2] >> 8) & 0x7F );
                        ii += 3;
                    }
                    printf ("\n");
                } else if (ident==3) {
                    /*
                    **  DBL record
                    */
                    if (list) {
                        printf ("DBL %c\n", (r[1] & 64) ? ' ' : 'Z' );
                        nn = r[1] & 63;
                        addr = r[3];
                        ii = 4;
                        jj = 0;
                        while (jj < nn) {
                            reloc = r[ii++];
                            for (kk=0 ; (kk<5) && (jj<nn) ; kk++) {
                                data = r[ii++];
                                ri = reloc >> (13 - 3*kk);
                                ri = ri & 7;
                                if (ri==5) data2 = r[ii++];
                                printf ("%05o %06o %d\n", addr, data, ri);
                                addr++;
                                jj++;
                            }
                        }
                    }

                } else if (ident==5) {
                    /*
                    **  END record
                    */
                    printf ("END %d %06o\n\n", (r[1] & 1) , r[3] );
                } else {
                    /*  Unknown record ident */
                    printf ("count=%d, ident=%d\n", count, ident);
                }

            }
        }
    }
    printf ("%d words checked\n", nbchecked);
}
