/*
 * WADWHAT.C - print the contents of a DOOM WAD file
 *
 * by Randall R. Spangler
 *
 * Version 1.1, released 8/28/94
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <dir.h>

struct s_thing {                /* Thing data */
    short int   x, y;           /* Coordinates */
    short int   facing;         /* Facing, in degrees */
    short int   type;           /* Type of thing */
    short int   attr;           /* Thing attributes */
};
typedef struct s_thing THING;

/***************************************************************************/

char        contents[10][9] =   /* Valid sub-entry names for a level */
{"THINGS", "LINEDEFS", "SIDEDEFS", "VERTEXES", "SEGS", "SSECTORS",
"NODES", "SECTORS", "REJECT", "BLOCKMAP"};

char        itemline[] = "\t%-20s %5ld %5ld %5ld %5ld + %5d %5d %5d %5d\n";     /* Line of text for an
                                                                                 * item */

/***************************************************************************/

int         isbrief = 0;        /* If non-zero, is the skill level we're
                                 * printing brief stats on */
int         battr = 0;          /* Matching attribute byte for brief printout */

int         battrarry[5] = {0x01, 0x01, 0x02, 0x04, 0x04};      /* Attribute bytes vs.
                                                                 * skill level */

FILE       *savefile;           /* WAD file whose things we're looking at */
long        savefilepos;        /* Save position in WAD file (where we were
                                 * before we started looking at THINGS,
                                 * LINEDEFS, or SECTORS) */

long        thoff = 0, thlen = 0;       /* Position and length of thing data */
long        ldoff = 0, ldlen = 0;       /* Position and length of linedef
                                         * data */
long        seoff = 0, selen = 0;       /* Position and length of sector data */
long        rjlen = 0;          /* Length of reject data */

THING      *th;                 /* Thing data for a level */
int         numth = 0;          /* Number of things */

char        buf[256];

/***************************************************************************/

long        countth(int type, int attr)
{
    /* Returns the number of things of the specified type with at least one
     * matching attribute bit.  If the multi-player bit in <attr> is on,
     * matches either single or multi-player; else matches single-player
     * only. <attr>=(-1) matches any skill or multi-player. */

    THING      *t = th;         /* Current thing */

    int         askill = attr & 0x07;   /* Skill bits of attribute */
    int         amp = attr & 0x10;      /* Multi-player bits of attribute */

    long        n = 0;          /* Number of matches */
    int         i;

    for (i = 0; i < numth; i++, t++) {  /* Search all things */
        if (t->type != type)
            continue;                   /* Wrong object */

        if (attr < 0)
            n++;                        /* Match all objects of this type */
        else if (t->attr & askill) {
            if (amp)
                n++;                    /* Want single or multi */
            else if (!(t->attr & 0x10))
                n++;                    /* Want single only */
        }
    }

    return n;                           /* Return match count */
}

/***************************************************************************/

long       *countdiff(int type, long *dest)
{
    /* Counts the number of things of the specified type at each difficulty
     * level.  dest[0]=L12, dest[1]=L3, dest[2]=L45, dest[3]=multiplayer
     * only. Returns a pointer to the destination array, or NULL if error. */

    THING      *t = th;
    int         i;

    for (i = 0; i < 6; i++)
        dest[i] = 0;                    /* Clear destination array */

    for (i = 0; i < numth; i++) {       /* Search all things */
        if (t->type == type) {          /* Matched type */
            if (t->attr & 0x00010) {    /* Multi-player only */
                if (t->attr & 0x0001)
                    dest[3]++;
                if (t->attr & 0x0002)
                    dest[4]++;
                if (t->attr & 0x0004)
                    dest[5]++;
            } else {                    /* Single-player only */
                if (t->attr & 0x0001)
                    dest[0]++;
                if (t->attr & 0x0002)
                    dest[1]++;
                if (t->attr & 0x0004)
                    dest[2]++;
            }
        }
        t++;                            /* Advance to next thing */
    }

    for (i = 0; i < 3; i++)
        dest[i + 3] += dest[i];         /* Single-player stuff is present in
                                         * multi-player too */

    return dest;                        /* Return match count */
}

/***************************************************************************/

long       *addcountweighted(int type, long *dest, int weight)
{
    /* Similar to countdiff(), but adds <weight> times the counts vs.
     * difficulty to the destination array instead of just setting it to the
     * match counts. Returns NULL if error. */

    long        nd[6];
    int         i;

    countdiff(type, nd);                /* Count the matches */

    for (i = 0; i < 6; i++)
        dest[i] += weight * nd[i];      /* Add a weighted result */

    return dest;
}

/***************************************************************************/
/***************************************************************************/

int         loadthings(FILE * f, long offs, long len)
{
    /* Loads a map's THINGS data at offset <offs>, length <len>.  Returns
     * zero if error. */

    savefile = f;               /* Save WAD file handle */
    savefilepos = ftell(f);             /* Save position in WAD file */

    fseek(f, offs, SEEK_SET);
    th = (THING *) malloc(len);
    if (!th) {
        fprintf(stderr, "Not enough memory to hold THINGS\n");
        return 0;
    }
    fread(th, 1, len, f);
    numth = len / 10;

    return 1;                           /* Success */
}

int         freethings(void)
{
    /* Frees a map's THINGS data loaded by loadthings().  Returns zero if
     * error. */

    free(th);
    numth = 0;

    fseek(savefile, savefilepos, SEEK_SET);

    return 1;                           /* Success */
}

/***************************************************************************/

void        printitem(char *desc, long *arry, int double1)
{
    /* Prints an item's presence at all skill levels.  If double1, doubles
     * the numbers in columns 1 and 5.  */

    int         i;

    for (i = 0; i < 6; i++)
        if (arry[i])
            break;

    if (i == 6)
        return;                         /* Item is not present at any skill
                                         * level */

    printf("\t%-20.20s", desc);         /* Print description */

    for (i = 0; i < 6; i++) {
        if (i == 3)
            printf(" |");
        if (i == 0 || i == 3)
            printf(" %5ld", (double1 ? 2 * arry[i] : arry[i]));
        printf(" %5ld", arry[i]);
    }
    printf("\n");
}


/***************************************************************************/

void        prtth(int type, char *desc)
{
    /* Prints the description and number of matching things at each
     * difficulty level. */

    long        nd[6] = {0, 0, 0, 0, 0, 0};     /* Numbers at each difficulty
                                                 * level */

    countdiff(type, nd);
    printitem(desc, nd, 0);
}

/***************************************************************************/

/* If there is at least one thing with id <no>, print the description of the
 * thing and the number present at each skill level. */
#define PRINTITEM(desc,arry) printitem(desc,arry,0)
#define PRINTITEM2(desc,arry) printitem(desc,arry,1)

/* Reset an array */
#define RESET(arry) for(i=0; i<6; i++) arry[i]=0

int         countthings(void)
{
    /* Counts the things in a level's THINGS data.  Returns zero if error. */

    long        nc[6] = {0, 0, 0, 0, 0, 0};     /* Number of things counted
                                                 * at each skill level */
    long        wdam[6] = {0, 0, 0, 0, 0, 0};   /* Total weapon damage at
                                                 * each skill level */
    float       dratio[6] = {0, 0, 0, 0, 0, 0}; /* Damage ratio for
                                                 * difficulty */
    int         n, i;

    /** Player starts **/

    printf("    Play modes:\n");

    if (countth(1, -1))                 /* Find player 1 start */
        printf("\tSingle player\n");
    n = 0;

    for (i = 1; i <= 4; i++) {          /* Find player 1-4 starts */
        if (countth(i, -1))
            n++;
    }
    if (n > 1)
        printf("\tCooperative (%d player)\n", n);

    n = countth(11, -1);                /* Find deathmatch starts */
    if (n)
        printf("\tDeathmatch (%d starts)\n", n);

    /** Monsters **/

    printf("    Bosses:\n");
    prtth(3003, "Baron");
    prtth(16, "Cyberdemon");
    prtth(7, "Spiderdemon");

    printf("    Monsters:\n");
    prtth(3004, "Trooper");
    prtth(9, "Sergeant");
    prtth(3001, "Imp");
    prtth(3002, "Demon");
    prtth(58, "Spectre");
    prtth(3006, "Lost soul");
    prtth(3005, "Cacodemon");

    printf("    Weapons:\n");
    prtth(2001, "Shotgun");
    prtth(2002, "Chaingun");
    prtth(2003, "Rocket launcher");
    prtth(2004, "Plasma gun");
    prtth(2006, "BFG-9000");
    prtth(2005, "Chainsaw");

    printf("    Equipment:\n");
    prtth(8, "Backpack");
    prtth(2022, "Invulnerability");
    prtth(2023, "Berserk");
    prtth(2024, "Invisibility");
    prtth(2025, "Radiation suit");
    prtth(2026, "Computer map");
    prtth(2045, "Lite amp goggles");

    printf("    Expendibles:\n");

    RESET(nc);
    addcountweighted(2002, nc, 20);     /* Chainguns */
    addcountweighted(2007, nc, 10);     /* Clips */
    addcountweighted(2048, nc, 50);     /* Boxes of ammo */
    addcountweighted(8, nc, 10);        /* Backpacks */
    addcountweighted(3004, nc, 5);      /* Troopers */
    PRINTITEM2("Bullets", nc);
    for (i = 0; i < 6; i++)
        wdam[i] += nc[i];               /* Accumulate damage */

    RESET(nc);
    addcountweighted(2001, nc, 8);      /* Shotguns */
    addcountweighted(2008, nc, 4);      /* Shells */
    addcountweighted(2049, nc, 20);     /* Boxes of shells */
    addcountweighted(8, nc, 4);         /* Backpacks */
    addcountweighted(9, nc, 4);         /* Sergeants */
    PRINTITEM2("Shells", nc);
    for (i = 0; i < 6; i++)
        wdam[i] += 7 * nc[i];           /* Accumulate damage */

    RESET(nc);
    addcountweighted(2003, nc, 2);      /* Rocket launchers */
    addcountweighted(2010, nc, 1);      /* Rockets */
    addcountweighted(2046, nc, 5);      /* Boxes of rockets */
    addcountweighted(8, nc, 1);         /* Backpacks */
    PRINTITEM2("Rockets", nc);
    for (i = 0; i < 6; i++)
        wdam[i] += 20 * nc[i];          /* Accumulate damage */

    RESET(nc);
    addcountweighted(2004, nc, 40);     /* Plasma guns */
    addcountweighted(2006, nc, 40);     /* BFG-9000's */
    addcountweighted(17, nc, 20);       /* Cell packs */
    addcountweighted(2047, nc, 100);    /* Cell charges */
    addcountweighted(8, nc, 20);        /* Backpacks */
    PRINTITEM2("Cells", nc);
    for (i = 0; i < 6; i++)
        wdam[i] += 2 * nc[i];           /* Accumulate damage */

    RESET(nc);
    addcountweighted(2018, nc, 100);    /* Armor */
    addcountweighted(2019, nc, 200);    /* Super armor */
    addcountweighted(2015, nc, 1);      /* Armor bonuses */
    PRINTITEM2("Armor points", nc);

    RESET(nc);
    addcountweighted(2011, nc, 10);     /* Stimpacks */
    addcountweighted(2012, nc, 25);     /* Medikits */
    addcountweighted(2013, nc, 100);    /* Soul spheres */
    addcountweighted(2023, nc, 100);    /* Berserk strength */
    addcountweighted(2014, nc, 1);      /* Health bonuses */
    PRINTITEM2("Health points", nc);

    prtth(2035, "Barrels");

    /* Calculate difficulty based on damage we can do vs. damage required to
     * kill all the monsters */

    printf("    Difficulty:\n");

    RESET(nc);
    addcountweighted(3004, nc, 2);      /* Troopers */
    addcountweighted(9, nc, 3);         /* Sergeants */
    addcountweighted(3001, nc, 6);      /* Imps */
    addcountweighted(3002, nc, 15);     /* Demons */
    addcountweighted(58, nc, 15);       /* Spectres */
    addcountweighted(3006, nc, 10);     /* Lost souls */
    addcountweighted(3005, nc, 40);     /* Cacodemons */
    addcountweighted(3003, nc, 100);    /* Barons */
    addcountweighted(16, nc, 400);      /* Cyberdemons */
    addcountweighted(7, nc, 300);       /* Spiderdemons */
    PRINTITEM("Total monster hp", nc);
    PRINTITEM2("Max ammo damage", wdam);

    for (i = 0; i < 6; i++) {
        if (!wdam[i])
            continue;
        dratio[i] = (wdam[i] ? (float) nc[i] / (float) wdam[i] : 0);    /* Prevent
                                                                         * divide-by-zero */
    }
    printf("\t%-20s %0.3f %0.3f %0.3f %0.3f", "RATIO", 0.5 * dratio[0], dratio[0], dratio[1], dratio[2]);
    printf(" | %0.3f %0.3f %0.3f %0.3f\n", 0.5 * dratio[3], dratio[3], dratio[4], dratio[5]);

    /*** Return success ***/

    return 1;
}

/***************************************************************************/

/* Item count */
#define COB(item) countth(item,battr)
/* Print a character if the item is present */
#define PRB0(item,char) printf("%c",(COB(item)?(char):'.'))
/* Print item count, one digit */
#define PRB1(item) {n=COB(item);printf((n>9?"+ ":"%d "),n);}
/* Print item count, two digits */
#define PRB2(item) {n=COB(item);printf((n>99?"++ ":"%2d "),n);}

int         countbriefly(void)
{
    /* Counts the things in a level, with one-line output format.  Returns
     * zero if error. */

    long        wdam = 0;       /* Total weapon damage */
    long        mhp = 0;        /* Total monster hit points */
    float       dratio;         /* Damage ratio */

    long        l;
    int         n, i;

    /*** Player starts ***/

    n = 0;
    for (i = 1; i <= 4; i++) {          /* Find player 1-4 starts */
        if (countth(i, -1))
            n++;
    }
    printf("  %d %2ld  ", n, countth(0x11, -1));        /* Find deathmatch
                                                         * starts */

    /*** Monsters ***/

    /* Bosses */
    PRB2(3003);
    PRB1(16);
    PRB1(7);

    /* Monsters */
    printf(" ");
    PRB2(3004);
    PRB2(9);
    PRB2(3001);
    PRB2(3002);
    PRB2(58);
    PRB2(3006);
    PRB2(3005);

    /* Weapons */
    putchar(' ');
    PRB0(2005, '1');
    putchar('2');
    PRB0(2001, '3');
    PRB0(2002, '4');
    PRB0(2003, '5');
    PRB0(2004, '6');
    PRB0(2006, '7');

    /* Equipment */
    printf("  ");
    PRB0(8, 'B');
    PRB0(2022, 'V');
    PRB0(2023, 'S');
    PRB0(2024, 'I');
    PRB0(2025, 'R');
    PRB0(2026, 'A');
    PRB0(2045, 'L');

    /*** Calculate damage ratio ***/

    /** Ammo from all sources **/

    l = 20 * COB(2002) + 10 * COB(2007) + 50 * COB(2048) + 10 * COB(8) + 5 * COB(3004);
    wdam += l;                          /* Bullets */

    l = 8 * COB(2001) + 4 * COB(2008) + 20 * COB(2049) + 4 * COB(8) + 4 * COB(9);
    wdam += 7 * l;                      /* Shells */

    l = 2 * COB(2003) + COB(2010) + 5 * COB(2046) + COB(8);
    wdam += 20 * l;                     /* Rockets */

    l = 40 * COB(2004) + 40 * COB(2006) + 20 * COB(17) + 100 * COB(2047) + 20 * COB(8);
    wdam += 2 * l;                      /* Cell packs */

    /** Monster hit points **/

    mhp = 2 * COB(3004) + 3 * COB(9) + 6 * COB(3001) + 15 * COB(3002) + 15 * COB(58)
          + 10 * COB(3006) + 40 * COB(3005) + 100 * COB(3003) + 400 * COB(16) + 300 * COB(7);

    dratio = (wdam ? (float) mhp / (float) wdam : 0);   /* Make sure we don't
                                                         * divide by zero */
    if (isbrief == 1)
        dratio *= 0.5;                  /* Twice as much ammo in easiest
                                         * level */

    printf("  %0.3f\n", dratio);

    /*** Return success ***/

    return 1;

}

/***************************************************************************/
/***************************************************************************/

int         countlinedefs(FILE * f, long offs, long len)
{
    /* Counts the interesting linedefs in a map's LINEDEFS data.  Returns
     * zero if error. */

    long        savepos = ftell(f);     /* Save position in WAD file */

    long        nlines = len / 14;      /* Total number of linedefs */
    long        ntrig = 0;      /* Number of linedefs which do something */

    int         ibuf[7];
    long        l;

    /*** Seek to the LINEDEFS data and loop through the linedefs ***/

    fseek(f, offs, SEEK_SET);

    for (l = 0; l < nlines; l++) {
        fread(ibuf, sizeof(int), 7, f); /* Read a linedef */

        if (ibuf[3])
            ntrig++;
    }

    /*** Print information ***/

    printf("\tTriggers / linedefs    %4ld / %4ld\n", ntrig, nlines);

    /*** Seek to original file position and return success ***/

    fseek(f, savepos, SEEK_SET);
    return 1;                           /* Success */
}

/***************************************************************************/

int         countsectors(FILE * f, long offs, long len)
{
    /* Counts the interesting sectors in a map's SECTORS data.  Returns zero
     * if error. */

    long        savepos = ftell(f);     /* Save position in WAD file */

    long        nsec = len / 26;/* Total number of sectors */
    long        bright = 0;     /* Average brightness */
    long        nnuke = 0;      /* Sectors with nukeage */
    long        nsecret = 0;    /* Secret sectors */

    int         ibuf[13];
    long        l;

    /*** Seek to the SECTORS data and loop through the sectors ***/

    fseek(f, offs, SEEK_SET);

    for (l = 0; l < nsec; l++) {
        fread(ibuf, sizeof(int), 13, f);/* Read a sector */

        bright += ibuf[10];             /* Accumulate brightness */

        switch (ibuf[11]) {             /* Check for specials */
          case 4:                       /* -20%, blinking */
          case 5:                       /* -10% */
          case 7:                       /* -5% */
          case 11:                      /* -20%, end of level */
          case 16:                      /* -20% */
            nnuke++;
            break;
          case 9:                       /* Secret */
            nsecret++;
            break;
        }
    }

    /*** Print information ***/

    printf("\tAverage brightness            %4ld (0=dark, 255=bright)\n", bright / nsec);

    printf("\tSecrets                       %4ld\n", nsecret);
    printf("\tNukeage / sectors      %4ld / %4ld\n", nnuke, nsec);

    /*** Seek to original file position and return success ***/

    fseek(f, savepos, SEEK_SET);
    return 1;                           /* Success */
}

/***************************************************************************/
/***************************************************************************/

int         PrintAllStuff(FILE * f)
{
    /* Prints all information for a map.  Returns zero if error. */


    /*** Print things ***/

    if (thlen) {
        if (loadthings(f, thoff, thlen)) {      /* Load things */
            if (isbrief)
                countbriefly(); /* Print brief counts */
            else
                countthings();          /* Print verbose counts */
            freethings();               /* Free array, restore original file
                                         * position */
        }
    }
    /*** If brief info, return now (no extended info) ***/

    if (isbrief)
        return 1;

    /*** Print other info ***/

    printf("    Other info:\n");

    if (selen)
        countsectors(f, seoff, selen);
    if (ldlen)
        countlinedefs(f, ldoff, ldlen);

    printf("\tReject resource                %s\n", (rjlen > 0 ? "YES" : " NO"));

    /*** Return success ***/

    return 1;
}

/***************************************************************************/

int         handlepwad(char *fname)
{
    /* Handles a PWAD file.  Returns zero if error. */

    int         ispwad = 0;     /* Are we a PWAD? (or an IWAD) */

    long        ndirent;        /* Number of entries in WAD directory */
    long        diroffs;        /* Offset of directory in WAD file */

    long        eoffs, elen;    /* Offset and length of a directory entry */
    char        ename[9] = "entrynam";  /* Name of the entry */
    int         episode = 0, mission = 0;       /* Current episode and
                                                 * mission */
    FILE       *f;
    int         i, j;

    /*** Open the PWAD file ***/

    f = fopen(fname, "rb");
    if (!f) {
        fprintf(stderr, "Can't open file %s\n", fname);
        return 0;
    }
    /*** Read the header ***/

    fread(buf, sizeof(char), 4, f);
    if (!strncmp(buf, "IWAD", 4)) {
        ispwad = 0;
    } else if (!strncmp(buf, "PWAD", 4)) {
        ispwad = 1;
    } else {
        printf("%s is not a DOOM WAD file\n", fname);
        fclose(f);
        return 0;
    }

    if (!isbrief) {                     /* Start a new filename in the output */
        printf("==============================================================================\n");
        printf("%cWAD FILE %s:\n", (ispwad ? 'P' : 'I'), fname);
    }
    fread(&ndirent, sizeof(long), 1, f);/* Number of entries in WAD dir */
    fread(&diroffs, sizeof(long), 1, f);/* Offset of directory in WAD */

    /*** Print the WAD directory ***/

    fseek(f, diroffs, SEEK_SET);        /* Go to the directory */

    for (i = 0; i < ndirent; i++) {

        /** Read entry **/

        fread(&eoffs, sizeof(long), 1, f);      /* Offset of entry's data */
        fread(&elen, sizeof(long), 1, f);       /* Length of entry's data */
        fread(&ename, sizeof(char), 8, f);      /* Name of entry */

        /** If entry is part of a level, print it **/

        for (j = 0; j < 10; j++) {
            if (!strcmp(ename, contents[j]))
                break;                  /* Matched valid contents for a level */
        }

        switch (j) {
          case 10:                      /* Not level contents */

            if (!mission)
                break;

            /** Look at all the stuff we found **/

            PrintAllStuff(f);

            /** Reset status **/

            thlen = ldlen = selen = rjlen = 0;
            episode = mission = 0;      /* No longer in a level */
            break;

          case 0:                       /* THINGS */
            thoff = eoffs;
            thlen = elen;
            break;

          case 1:                       /* LINEDEFS */
            ldoff = eoffs;
            ldlen = elen;
            break;
          case 7:                       /* SECTORS */
            seoff = eoffs;
            selen = elen;
            break;
          case 8:                       /* REJECT */
            rjlen = elen;
            break;
        }

        /** Keep track of which mission we're looking at **/

        if (ename[0] == 'E' && isdigit(ename[1]) && ename[2] == 'M' &&
            isdigit(ename[3]) && ename[4] == '\0') {
            episode = ename[1] - '0';
            mission = ename[3] - '0';

            if (isbrief) {              /* One-line output */
                printf("%-12.12s E%dM%d", fname, episode, mission);
            } else {                    /* Verbose output */
                printf("------------------------------------------------------------------------------\n");
                printf("EPISODE %d MISSION %d             S1    S2    S3   S45 |    M1    M2    M3   M45\n", episode, mission);
                printf("------------------------------------------------------------------------------\n");
            }
        }
    }

    /*** Look at all the stuff we found from the last map, if any ***/

    if (mission)
        PrintAllStuff(f);
    thlen = ldlen = selen = rjlen = 0;

    /*** Close the file and return success ***/

    fclose(f);
    return 1;
}

/***************************************************************************/
/***************************************************************************/

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

    struct ffblk ff;
    int         i;

    /*** Make sure we've been given a filename ***/

    printf("WADWHAT 1.1 by Randall R. Spangler (rspangle@micro.caltech.edu)\n");

    if (argc < 2) {
        printf("Prints the contents of a WAD file or files.\n");
        printf("Usage:\n\twadwhat [-Bn[M]] file1 [file2 ...]\n");
        printf("\n\t\t-Bn\tbrief contents at skill level n\n");
        printf("\t\t-BnM\tbrief contents at skill level n, multiplayer\n");
        return 1;
    }
    /*** Match all wildcards ***/

    for (i = 1; i < argc; i++) {

        /** See if we're an option **/

        if (!strnicmp(argv[i], "-B", 2)) {      /* Print briefly */
            isbrief = atoi(argv[i] + 2);/* Extract skill level */
            printf("File         Map   Play  Bosses  Monsters              Weapons  Equip    RATIO\n");
            printf("-------------------c-de--ba-c-s--tr-se-im-de-sp-lo-ca--cpscrpb--bvsiral-------\n");
            battr = battrarry[isbrief - 1];     /* Matching attributes for
                                                 * brief printout */
            if (toupper(argv[i][3]) == 'M')
                battr |= 0x10;          /* Add in multi-player stuff */

            continue;
        }
        /** Make sure at least one matching file exists **/

        if (findfirst(argv[i], &ff, FA_ARCH)) { /* No match for wildcard */
            fprintf(stderr, "Can't find file matching %s\n", argv[i]);
            continue;
        }
        /** Handle all the matching files **/

        do {
            handlepwad(ff.ff_name);
        } while (!findnext(&ff));
    }

    /*** Return success ***/

    return 0;
}

/***************************************************************************/
/***************************************************************************/
