// (c) 1993-2007 Electronic Arts Inc.

const char *SPIT_history[] =
{
"------------------------------------------------------------------",
"                                                                  ",
"                         BinGrep v1.03                            ",
"                                                                  ",
"                     by FrANK G. Barchard, EAC                    ",
"                                                                  ",
"                   Main program - Sep 29, 2001                    ",
"                                                                  ",
"------------------------------------------------------------------",
"                                                                  ",
" Version Date   History:                                          ",
" ------- ------ --------                                          ",
"    1.00 941213 BinGrep based on CRC to find binary word in files ",
"    1.01 941213 Handle binary stream rather than words            ",
"    1.02 950307 Show occurance number                             ",
"    1.03 010929 fix up doc                                        ",
"                                                                  ",
"------------------------------------------------------------------",
"\0"
};

/****************************************************************/
/*  Spit Setup                                                  */
/****************************************************************/

#include    "spit.h"

const char TextVersion[]="1.03 (Samba) 2007.12.4";
#define TOOL_VERSION 103
#define TOOL_NAME "bingrep"

#define MAXWORDS 256
int OPTnumwords;
unsigned char OPTwords[MAXWORDS];

int checkmatch(const char *s)
{
    int i;
    unsigned int w;

    for (i=0; i<OPTnumwords; ++i)
    {
        w = ggetm(s,1);
        if ((unsigned char) w != (unsigned char) OPTwords[i])
            return(0);
        s += 1;
    }
    return(1);
}

int SPIT_bingrep(char *s,int len)
{
    register char               *end;
    int                        woff;
    int                         numfound=0;

    woff = 0L;
    end = s+len-OPTnumwords+1;
    if (s<end)
    {
        do
        {
            if (checkmatch(s))
            {
                if (!numfound)
                    if (OPTverbose>=3)
                        puts("Found:");
                if (OPTverbose>=3)
                    printf(" #%-3d $%05lx (%ld)\n",numfound,woff,woff);
                ++numfound;
            }
            ++s;
            ++woff;
        } while (s<end);
    }
    return(numfound);
}

int getnibble(const char *s)
{
    int c;
    int n;

    c = ggetm(s,1);

    n = -1;
    if (c>='0' && c<='9')       n = c - '0';
    else if (c>='a' && c<='f')  n = c - ('a'-10);
    else if (c>='A' && c<='F')  n = c - ('A'-10);

    return(n);
}

#if 0
;
; ABSTRACT
;
; bingrep - greps thru binary data files
;
; SUMMARY
;
; bingrep -options [hexvalue] [files]
;     @file     response file, containing a list of options and files
;     -nologo   disable banner
;     -v0       no console output
;     -v1       prints source file name and errors
;     -v2       status line for each file (default)
;     -v3       additional info
;     -r        recurse subdirectories
;
; DESCRIPTION
;
; The bingrep tool searches binary files for a specified sequence
; of bytes, specified in hexadecimal
;
; RETURNS
;
; no return code
;
; SEE ALSO
;
; cmp, xd, Spit
;
; SAMPLE OUTPUT
;
; E:\tools\gx>bingrep 0x45525453 john.fsh
; BinGrep v1.02 (dixieme) 010926 (c) 1992 FrANK G. Barchard
; john.fsh: Reading, Grepping, Found:
;  #0   $0001c (28)
; Occurances 1 ($0001)
;
; END ABSTRACT
;
#endif

/****************************************************************/
/*  SPIT Routines                                               */
/****************************************************************/

void SPIT_reset(void)
{
    OPTwrite = 0;
    OPTminargs = 2;
    return;
}

void SPIT_usage(const char *prgname, const char *envname, const char *urlname, int utype)
{
    printf("BinGrep v%s (c) 1992 FrANK G. Barchard\n",TextVersion);

    if (utype)
        printf("USAGE: %s -options [hexstring] [files]\n", prgname);

    switch (utype)
    {
        case 0:
        case 1:
            break;

        case 2:
            puts("     @ response file       ");
            puts("    -v verbose");
            puts("    -r recurse subdirectories");
          printf("type '%s -h' for more help\n", prgname);
          printf("type '%s -help' for web page (%s)\n", prgname, urlname);
            break;

        case 3:
            puts("");
          printf("VERSION: %s v%s, Spit v%.2f\n",SPIT_MACHINE,TextVersion,(float)SPIT_VERSION/100.0f);
            puts("SUMMARY: BinGrep searches for binary words in files");
          printf("         SPIT environment variable is %s\n",envname);
            puts("");
            puts("    @file     response file, containing a list of options and files");
            puts("    -.(list)  list of extensions to try for source files ie -.(c h)");
            puts("    -nologo   disable banner");
            puts("    -v0       no console output");
            puts("    -v1       prints source file name and errors");
            puts("    -v2       status line for each file (default)");
            puts("    -v3       additional info");
            puts("    -r        recurse subdirectories");
            break;

        default:
            break;
    }
}

char *SPIT_opt(const char *optptr)
{
    return((char *) 0);
}


int main(int argc,char *argv[])
{
    int more;
    int i;
    int bingrep;
    struct SPITMEM infile;
    char *s;
    unsigned int w;
    int nibblel;
    int nibbleh;
    int ok;

    SPIT_init(SPIT_reset, SPIT_usage, SPIT_opt, SPIT_history);
    do
    {
        more = SPIT_parse(argc, argv, TOOL_NAME, TOOL_VERSION);

        if (SPITargnum>=2)
        {
            s = SPITsargv[0];
            OPTnumwords = 0;
            ok = 1;
            while (ok && *s)
            {
                if (*s=='$')
                    ++s;
                if (*s=='0' && (*(s+1)|' ')=='x')
                    s += 2;

                w = 0;

                ok = 0;
                nibbleh = getnibble(s);
                if (nibbleh>=0)
                {
                    nibblel = getnibble(s+1);
                    if (nibblel>=0)
                    {
                        s += 2;
                        ok = 1;
                        w = (nibbleh<<4)|nibblel;

                        if (OPTverbose>=4)
                        {
                            printf("word %d: [%04lx]\n",OPTnumwords,w);
                        }
                        OPTwords[OPTnumwords++] = (unsigned char)w;

                        /* valid seperators between bytes */
                        if (*s==','
                         || *s==' '
                         || *s=='.'
                         || *s=='_'
                         || *s=='|'
                         || *s=='/'
                         || *s=='#'
                         || *s=='$'
                         || *s==';'
                         || *s==':'
                         || *s=='-')
                            ++s;
                    }
                }
            }
            ok = 1;
            if (*s>' ')
            {
                ok = 0;
                if (OPTverbose)
                    printf("invalid hexstring.  ie  aa55ff123400\n");
            }
            if (ok)
            {
                for (i=1; i<SPITargnum; ++i)
                {
                    if (SPIT_loadfile(&infile, SPITsargv[i]))
                    {
                        if (OPTverbose>=3)
                        {   printf("Grepping, ");
                            SPIT_flush();
                        }

                        bingrep = SPIT_bingrep(infile.ptr, infile.len);

                        SPIT_free(&infile);

                        if (OPTverbose)
                        {
                            if (OPTverbose>=3)
                                printf("Occurances %d ($%04x)\n", bingrep, bingrep);
                            else
                                printf("Occurances $%04x ", bingrep);
                            SPIT_flush();
                        }
                    }
                }
            }
        }
    } while (more>0);

    if (OPTverbose==1)
        puts("");
    return(0);
}

