home *** CD-ROM | disk | FTP | other *** search
/ Doom 2 Explosion / Doom2Explosion.bin / doom2exp / programs / wadwha10 / wadwhat.c < prev    next >
C/C++ Source or Header  |  1994-08-22  |  21KB  |  601 lines

  1. /*
  2.  * WADWHAT.C - print the contents of a DOOM WAD file
  3.  *
  4.  * by Randall R. Spangler
  5.  *
  6.  * $Revision: 1.7 $ $Date: 1994/08/22 03:51:43 $
  7.  *
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <dos.h>
  15. #include <dir.h>
  16.  
  17. struct s_thing {                /* Thing data */
  18.     int         x, y;           /* Coordinates */
  19.     int         facing;         /* Facing, in degrees */
  20.     int         type;           /* Type of thing */
  21.     int         attr;           /* Thing attributes */
  22. };
  23. typedef struct s_thing THING;
  24.  
  25. /***************************************************************************/
  26.  
  27. char        contents[10][9] =   /* Valid sub-entry names for a level */
  28. {"THINGS", "LINEDEFS", "SIDEDEFS", "VERTEXES", "SEGS", "SSECTORS",
  29. "NODES", "SECTORS", "REJECT", "BLOCKMAP"};
  30.  
  31. char        itemline[] = "\t%-20s %5d %5d %5d %5d + %5d\n";     /* Line of text for an
  32.                                                                  * item */
  33.  
  34. /***************************************************************************/
  35.  
  36. int         isbrief = 0;        /* If non-zero, is the skill level we're
  37.                                  * printing brief stats on */
  38. int         battr = 0;          /* Matching attribute byte for brief printout */
  39.  
  40. int         battrarry[5] = {0x01, 0x01, 0x02, 0x04, 0x04};      /* Attribute bytes vs.
  41.  
  42.                                                                  * skill level */
  43.  
  44. FILE       *savefile;           /* WAD file whose things we're looking at */
  45. long        savefilepos;        /* Save position in WAD file (where we were
  46.                                  * before we started looking at THINGS) */
  47. THING      *th;                 /* Thing data for a level */
  48. int         numth = 0;          /* Number of things */
  49.  
  50. char        buf[256];
  51.  
  52. /***************************************************************************/
  53.  
  54. int         countth(int type, int attr)
  55. {
  56.     /* Returns the number of things of the specified type with at least one
  57.      * matching attribute bit. */
  58.  
  59.     THING      *t = th;
  60.     int         n = 0;
  61.     int         i;
  62.  
  63.     for (i = 0; i < numth; i++) {       /* Search all things */
  64.         if ((t->type == type) && ((t->attr) & attr))
  65.             n++;                        /* Found a match */
  66.         t++;                            /* Advance to next thing */
  67.     }
  68.  
  69.     return n;                           /* Return match count */
  70. }
  71.  
  72. /***************************************************************************/
  73.  
  74. int        *countdiff(int type, int *dest)
  75. {
  76.     /* Counts the number of things of the specified type at each difficulty
  77.      * level.  dest[0]=L12, dest[1]=L3, dest[2]=L45, dest[3]=multiplayer
  78.      * only. Returns a pointer to the destination array, or NULL if error. */
  79.  
  80.     THING      *t = th;
  81.     int         i;
  82.  
  83.     dest[0] = dest[1] = dest[2] = dest[3] = 0;  /* Clear destination array */
  84.  
  85.  
  86.     for (i = 0; i < numth; i++) {       /* Search all things */
  87.         if (t->type == type) {          /* Matched type */
  88.             if (t->attr & 0x0001)
  89.                 dest[0]++;
  90.             if (t->attr & 0x0002)
  91.                 dest[1]++;
  92.             if (t->attr & 0x0004)
  93.                 dest[2]++;
  94.             if (t->attr & 0x00010)
  95.                 dest[3]++;
  96.         }
  97.         t++;                            /* Advance to next thing */
  98.     }
  99.  
  100.     return dest;                        /* Return match count */
  101. }
  102.  
  103. /***************************************************************************/
  104.  
  105. int         prtth(int type, char *desc)
  106. {
  107.     /* Prints the description and number of matching things at each
  108.      * difficulty level. Returns zero if error. */
  109.  
  110.     int         nd[4];          /* Numbers at each difficulty level */
  111.  
  112.     countdiff(type, nd);
  113.  
  114.     if (nd[0] + nd[1] + nd[2] + nd[3] == 0)
  115.         return 0;                       /* No matching things */
  116.  
  117.     printf(itemline, desc, nd[0], nd[0], nd[1], nd[2], nd[3]);
  118.     return 1;
  119. }
  120.  
  121. /***************************************************************************/
  122.  
  123. int        *addcountweighted(int type, int *dest, int weight)
  124. {
  125.     /* Similar to countdiff(), but adds <weight> times the counts vs.
  126.      * difficulty to the destination array instead of just setting it to the
  127.      * match counts. Returns NULL if error. */
  128.  
  129.     int         nd[4];
  130.     int         i;
  131.  
  132.     countdiff(type, nd);                /* Count the matches */
  133.  
  134.     for (i = 0; i < 4; i++)
  135.         dest[i] += weight * nd[i];      /* Add a weighted result */
  136.  
  137.     return dest;
  138. }
  139.  
  140. /***************************************************************************/
  141. /***************************************************************************/
  142.  
  143. int         loadthings(FILE * f, long offs, long len)
  144. {
  145.     /* Loads a map's THINGS data at offset <offs>, length <len>.  Returns
  146.      * zero if error. */
  147.  
  148.     savefile = f;               /* Save WAD file handle */
  149.     savefilepos = ftell(f);             /* Save position in WAD file */
  150.  
  151.     fseek(f, offs, SEEK_SET);
  152.     th = (THING *) malloc(len);
  153.     if (!th) {
  154.         fprintf(stderr, "Not enough memory to hold THINGS\n");
  155.         return 0;
  156.     }
  157.     fread(th, 1, len, f);
  158.     numth = len / 10;
  159.  
  160.     return 1;                           /* Success */
  161. }
  162.  
  163. int         freethings(void)
  164. {
  165.     /* Frees a map's THINGS data loaded by loadthings().  Returns zero if
  166.      * error. */
  167.  
  168.     free(th);
  169.     numth = 0;
  170.  
  171.     fseek(savefile, savefilepos, SEEK_SET);
  172.  
  173.     return 1;                           /* Success */
  174. }
  175.  
  176. /***************************************************************************/
  177. /***************************************************************************/
  178.  
  179. /* If there is at least one thing with id <no>, print the description of the
  180.  * thing and the number present at each skill level. */
  181. #define PRINTITEM(desc,arry)\
  182. if((arry)[0]+(arry)[1]+(arry)[2]+(arry)[3])\
  183.    printf(itemline,desc,(arry)[0],(arry)[0],(arry)[1],(arry)[2],(arry)[3])
  184.  
  185. /* Same as above, but L1 is doubled (all ammo is doubled in skill level #1) */
  186. #define PRINTITEM2(desc,arry)\
  187. if((arry)[0]+(arry)[1]+(arry)[2]+(arry)[3])\
  188.    printf(itemline,desc,2*(arry)[0],(arry)[0],(arry)[1],(arry)[2],(arry)[3])
  189.  
  190. int         countthings(void)
  191. {
  192.     /* Counts the things in a level's THINGS data.  Returns zero if error. */
  193.  
  194.     int         nc[4];          /* Number of things counted at each skill
  195.                                  * level */
  196.     int         wdam[4] = {0, 0, 0, 0}; /* Total weapon damage at each skill
  197.                                          * level */
  198.     float       dratio[4] = {0, 0, 0, 0};       /* Damage ratio for
  199.                                                  * difficulty */
  200.     int         n, i;
  201.  
  202.     /** Player starts **/
  203.  
  204.     printf("    Play modes:\n");
  205.  
  206.     if (countth(1, 0x07))               /* Find player 1 start */
  207.         printf("\tSingle player\n");
  208.     n = 0;
  209.  
  210.     for (i = 1; i <= 4; i++) {          /* Find player 1-4 starts */
  211.         if (countth(i, 0x17))
  212.             n++;
  213.     }
  214.     if (n > 1)
  215.         printf("\tCooperative (%d player)\n", n);
  216.  
  217.     n = countth(11, 0x17);              /* Find deathmatch starts */
  218.     if (n)
  219.         printf("\tDeathmatch (%d starts)\n", n);
  220.  
  221.     /** Monsters **/
  222.  
  223.     printf("    Bosses:\n");
  224.     prtth(3003, "Baron");
  225.     prtth(16, "Cyberdemon");
  226.     prtth(7, "Spiderdemon");
  227.  
  228.     printf("    Monsters:\n");
  229.     prtth(3004, "Trooper");
  230.     prtth(9, "Sergeant");
  231.     prtth(3001, "Imp");
  232.     prtth(3002, "Demon");
  233.     prtth(58, "Spectre");
  234.     prtth(3006, "Lost soul");
  235.     prtth(3005, "Cacodemon");
  236.  
  237.     printf("    Weapons:\n");
  238.     prtth(2001, "Shotgun");
  239.     prtth(2002, "Chaingun");
  240.     prtth(2003, "Rocket launcher");
  241.     prtth(2004, "Plasma gun");
  242.     prtth(2006, "BFG-9000");
  243.     prtth(2005, "Chainsaw");
  244.  
  245.     printf("    Equipment:\n");
  246.     prtth(8, "Backpack");
  247.     prtth(2022, "Invulnerability");
  248.     prtth(2023, "Berserk");
  249.     prtth(2024, "Invisibility");
  250.     prtth(2025, "Radiation suit");
  251.     prtth(2026, "Computer map");
  252.     prtth(2027, "Lite amp goggles");
  253.  
  254.     printf("    Expendibles:\n");
  255.  
  256.     nc[0] = nc[1] = nc[2] = nc[3] = 0;
  257.     addcountweighted(2002, nc, 20);     /* Chainguns */
  258.     addcountweighted(2007, nc, 10);     /* Clips */
  259.     addcountweighted(2048, nc, 50);     /* Boxes of ammo */
  260.     addcountweighted(8, nc, 10);        /* Backpacks */
  261.     addcountweighted(3004, nc, 5);      /* Troopers */
  262.     PRINTITEM2("Bullets", nc);
  263.     for (i = 0; i < 4; i++)
  264.         wdam[i] += nc[i];               /* Accumulate damage */
  265.  
  266.     nc[0] = nc[1] = nc[2] = nc[3] = 0;
  267.     addcountweighted(2001, nc, 8);      /* Shotguns */
  268.     addcountweighted(2008, nc, 4);      /* Shells */
  269.     addcountweighted(2049, nc, 20);     /* Boxes of shells */
  270.     addcountweighted(8, nc, 4);         /* Backpacks */
  271.     addcountweighted(9, nc, 4);         /* Sergeants */
  272.     PRINTITEM2("Shells", nc);
  273.     for (i = 0; i < 4; i++)
  274.         wdam[i] += 7 * nc[i];           /* Accumulate damage */
  275.  
  276.     nc[0] = nc[1] = nc[2] = nc[3] = 0;
  277.     addcountweighted(2003, nc, 2);      /* Rocket launchers */
  278.     addcountweighted(2010, nc, 1);      /* Rockets */
  279.     addcountweighted(2046, nc, 5);      /* Boxes of rockets */
  280.     addcountweighted(8, nc, 1);         /* Backpacks */
  281.     PRINTITEM2("Rockets", nc);
  282.     for (i = 0; i < 4; i++)
  283.         wdam[i] += 20 * nc[i];          /* Accumulate damage */
  284.  
  285.     nc[0] = nc[1] = nc[2] = nc[3] = 0;
  286.     addcountweighted(2004, nc, 40);     /* Plasma guns */
  287.     addcountweighted(2006, nc, 40);     /* BFG-9000's */
  288.     addcountweighted(17, nc, 20);       /* Cell packs */
  289.     addcountweighted(2047, nc, 100);    /* Cell charges */
  290.     addcountweighted(8, nc, 20);        /* Backpacks */
  291.     PRINTITEM2("Cells", nc);
  292.     for (i = 0; i < 4; i++)
  293.         wdam[i] += 2 * nc[i];           /* Accumulate damage */
  294.  
  295.     nc[0] = nc[1] = nc[2] = nc[3] = 0;
  296.     addcountweighted(2018, nc, 100);    /* Armor */
  297.     addcountweighted(2019, nc, 200);    /* Super armor */
  298.     addcountweighted(2015, nc, 1);      /* Armor bonuses */
  299.     PRINTITEM2("Armor points", nc);
  300.  
  301.     nc[0] = nc[1] = nc[2] = nc[3] = 0;
  302.     addcountweighted(2011, nc, 10);     /* Stimpacks */
  303.     addcountweighted(2012, nc, 25);     /* Medikits */
  304.     addcountweighted(2013, nc, 100);    /* Soul spheres */
  305.     addcountweighted(2023, nc, 100);    /* Berserk strength */
  306.     addcountweighted(2014, nc, 1);      /* Health bonuses */
  307.     PRINTITEM2("Health points", nc);
  308.  
  309.     prtth(2035, "Barrels");
  310.  
  311.     /* Calculate difficulty based on damage we can do vs. damage required to
  312.      * kill all the monsters */
  313.  
  314.     printf("    Difficulty:\n");
  315.  
  316.     nc[0] = nc[1] = nc[2] = nc[3] = 0;
  317.     addcountweighted(3004, nc, 2);      /* Troopers */
  318.     addcountweighted(9, nc, 3);         /* Sergeants */
  319.     addcountweighted(3001, nc, 6);      /* Imps */
  320.     addcountweighted(3002, nc, 15);     /* Demons */
  321.     addcountweighted(58, nc, 15);       /* Spectres */
  322.     addcountweighted(3006, nc, 10);     /* Lost souls */
  323.     addcountweighted(3005, nc, 40);     /* Cacodemons */
  324.     addcountweighted(3003, nc, 100);    /* Barons */
  325.     addcountweighted(16, nc, 400);      /* Cyberdemons */
  326.     addcountweighted(7, nc, 300);       /* Spiderdemons */
  327.     PRINTITEM("Total monster hp", nc);
  328.     PRINTITEM2("Max ammo damage", wdam);
  329.  
  330.     for (i = 0; i < 4; i++) {
  331.         if (!wdam[i])
  332.             continue;
  333.         dratio[i] = (float) nc[i] / (float) wdam[i];
  334.     }
  335.     printf("\t%-20s %0.3f %0.3f %0.3f %0.3f + %0.3f\n", "RATIO", 0.5 * dratio[0], dratio[0], dratio[1], dratio[2], dratio[3]);
  336.  
  337.     /*** Return success ***/
  338.  
  339.     return 1;
  340. }
  341.  
  342. /***************************************************************************/
  343.  
  344. /* Item count */
  345. #define COB(item) countth(item,battr)
  346. /* Print a character if the item is present */
  347. #define PRB0(item,char) printf("%c",(COB(item)?(char):'.'))
  348. /* Print item count, one digit */
  349. #define PRB1(item) {n=COB(item);printf((n>9?"+ ":"%d "),n);}
  350. /* Print item count, two digits */
  351. #define PRB2(item) {n=COB(item);printf((n>99?"++ ":"%2d "),n);}
  352.  
  353. int         countbriefly(void)
  354. {
  355.     /* Counts the things in a level, with one-line output format.  Returns
  356.      * zero if error. */
  357.  
  358.     long        wdam = 0;       /* Total weapon damage */
  359.     long        mhp = 0;        /* Total monster hit points */
  360.     float       dratio;         /* Damage ratio */
  361.  
  362.     int         n, i;
  363.  
  364.     /*** Player starts ***/
  365.  
  366.     n = 0;
  367.     for (i = 1; i <= 4; i++) {          /* Find player 1-4 starts */
  368.         if (countth(i, 0x17))
  369.             n++;
  370.     }
  371.     printf("  %d %2d  ", n, COB(11));   /* Find deathmatch starts */
  372.  
  373.     /*** Monsters ***/
  374.  
  375.     /* Bosses */
  376.     PRB2(3003);
  377.     PRB1(16);
  378.     PRB1(7);
  379.  
  380.     /* Monsters */
  381.     printf(" ");
  382.     PRB2(3004);
  383.     PRB2(9);
  384.     PRB2(3001);
  385.     PRB2(3002);
  386.     PRB2(58);
  387.     PRB2(3006);
  388.     PRB2(3005);
  389.  
  390.     /* Weapons */
  391.     putchar(' ');
  392.     PRB0(2005, '1');
  393.     putchar('2');
  394.     PRB0(2001, '3');
  395.     PRB0(2002, '4');
  396.     PRB0(2003, '5');
  397.     PRB0(2004, '6');
  398.     PRB0(2006, '7');
  399.  
  400.     /* Equipment */
  401.     printf("  ");
  402.     PRB0(8, 'B');
  403.     PRB0(2022, 'V');
  404.     PRB0(2023, 'S');
  405.     PRB0(2024, 'I');
  406.     PRB0(2025, 'R');
  407.     PRB0(2026, 'A');
  408.     PRB0(2027, 'L');
  409.  
  410.     /*** Calculate damage ratio ***/
  411.  
  412.     /** Ammo from all sources **/
  413.  
  414.     n = 20 * COB(2002) + 10 * COB(2007) + 50 * COB(2048) + 10 * COB(8) + 5 * COB(3004);
  415.     wdam += n;                          /* Bullets */
  416.  
  417.     n = 8 * COB(2001) + 4 * COB(2008) + 20 * COB(2049) + 4 * COB(8) + 4 * COB(9);
  418.     wdam += 7 * n;                      /* Shells */
  419.  
  420.     n = 2 * COB(2003) + COB(2010) + 5 * COB(2046) + COB(8);
  421.     wdam += 20 * n;                     /* Rockets */
  422.  
  423.     n = 40 * COB(2004) + 40 * COB(2006) + 20 * COB(17) + 100 * COB(2047) + 20 * COB(8);
  424.     wdam += 2 * n;                      /* Cell packs */
  425.  
  426.     /** Monster hit points **/
  427.  
  428.     mhp = 2 * COB(3004) + 3 * COB(9) + 6 * COB(3001) + 15 * COB(3002) + 15 * COB(58)
  429.           + 10 * COB(3006) + 40 * COB(3005) + 100 * COB(3003) + 400 * COB(16) + 300 * COB(7);
  430.  
  431.     dratio = (float) mhp / (float) wdam;
  432.     if (isbrief == 1)
  433.         dratio *= 0.5;                  /* Twice as much ammo in easiest
  434.                                          * level */
  435.  
  436.     printf("  %0.3f\n", dratio);
  437.  
  438.     /*** Return success ***/
  439.  
  440.     return 1;
  441.  
  442. }
  443.  
  444. /***************************************************************************/
  445.  
  446. int         handlepwad(char *fname)
  447. {
  448.     /* Handles a PWAD file.  Returns zero if error. */
  449.  
  450.     int         ispwad = 0;     /* Are we a PWAD? (or an IWAD) */
  451.  
  452.     long        ndirent;        /* Number of entries in WAD directory */
  453.     long        diroffs;        /* Offset of directory in WAD file */
  454.  
  455.     long        eoffs, elen;    /* Offset and length of a directory entry */
  456.     char        ename[9] = "entrynam";  /* Name of the entry */
  457.     int         episode = 0, mission = 0;       /* Current episode and
  458.                                                  * mission */
  459.     FILE       *f;
  460.     int         i, j;
  461.  
  462.     /*** Open the PWAD file ***/
  463.  
  464.     f = fopen(fname, "rb");
  465.     if (!f) {
  466.         fprintf(stderr, "Can't open file %s\n", fname);
  467.         return 0;
  468.     }
  469.     /*** Read the header ***/
  470.  
  471.     fread(buf, sizeof(char), 4, f);
  472.     if (!strncmp(buf, "IWAD", 4)) {
  473.         ispwad = 0;
  474.     } else if (!strncmp(buf, "PWAD", 4)) {
  475.         ispwad = 1;
  476.     } else {
  477.         printf("%s is not a DOOM WAD file\n", fname);
  478.         fclose(f);
  479.         return 0;
  480.     }
  481.  
  482.     if (!isbrief) {                     /* Start a new filename in the output */
  483.         printf("============================================================\n");
  484.         printf("%cWAD FILE %s:\n", (ispwad ? 'P' : 'I'), fname);
  485.     }
  486.     fread(&ndirent, sizeof(long), 1, f);/* Number of entries in WAD dir */
  487.     fread(&diroffs, sizeof(long), 1, f);/* Offset of directory in WAD */
  488.  
  489.     /*** Print the WAD directory ***/
  490.  
  491.     fseek(f, diroffs, SEEK_SET);        /* Go to the directory */
  492.  
  493.     for (i = 0; i < ndirent; i++) {
  494.  
  495.         /** Read entry **/
  496.  
  497.         fread(&eoffs, sizeof(long), 1, f);      /* Offset of entry's data */
  498.         fread(&elen, sizeof(long), 1, f);       /* Length of entry's data */
  499.         fread(&ename, sizeof(char), 8, f);      /* Name of entry */
  500.  
  501.         /** Keep track of which mission we're looking at **/
  502.  
  503.         if (ename[0] == 'E' && isdigit(ename[1]) && ename[2] == 'M' &&
  504.             isdigit(ename[3]) && ename[4] == '\0') {
  505.             episode = ename[1] - '0';
  506.             mission = ename[3] - '0';
  507.  
  508.             if (isbrief) {              /* One-line output */
  509.                 printf("%-12.12s E%dM%d", fname, episode, mission);
  510.             } else {                    /* Verbose output */
  511.                 printf("------------------------------------------------------------\n");
  512.                 printf("EPISODE %d MISSION %d             L1    L2    L3   L45 + multi\n", episode, mission);
  513.                 printf("------------------------------------------------------------\n");
  514.             }
  515.         }
  516.         /** If entry is part of a level, print it **/
  517.  
  518.         for (j = 0; j < 10; j++) {
  519.             if (!strcmp(ename, contents[j]))
  520.                 break;                  /* Matched valid contents for a level */
  521.         }
  522.  
  523.         if (j == 10) {                  /* Didn't match level contents */
  524.             episode = mission = 0;      /* No longer in a level */
  525.             continue;                   /* Not valid part of a level */
  526.         }
  527.         if (j == 0) {                   /* Things */
  528.             if (!loadthings(f, eoffs, elen))    /* Load things */
  529.                 continue;
  530.             if (isbrief)
  531.                 countbriefly();         /* Print brief counts */
  532.             else
  533.                 countthings();          /* Print verbose counts */
  534.             freethings();               /* Free array, restore original file
  535.                                          * position */
  536.         }
  537.     }
  538.  
  539.     /*** Close the file and return success ***/
  540.  
  541.     fclose(f);
  542.     return 1;
  543. }
  544.  
  545. /***************************************************************************/
  546. /***************************************************************************/
  547.  
  548. int         main(int argc, char *argv[])
  549. {
  550.  
  551.     struct ffblk ff;
  552.     int         i;
  553.  
  554.     /*** Make sure we've been given a filename ***/
  555.  
  556.     printf("WADWHAT 1.0 by Randall R. Spangler (rspangle@micro.caltech.edu)\n");
  557.  
  558.     if (argc < 2) {
  559.         printf("Prints the contents of a WAD file or files.\n");
  560.         printf("Usage:\n\twadwhat [-Bn[M]] file1 [file2 ...]\n");
  561.         printf("\n\t\t-Bn\tbrief contents at skill level n\n");
  562.         printf("\t\t-BnM\tbrief contents at skill level n, multiplayer\n");
  563.         return 1;
  564.     }
  565.     /*** Match all wildcards ***/
  566.  
  567.     for (i = 1; i < argc; i++) {
  568.  
  569.         /** See if we're an option **/
  570.  
  571.         if (!strnicmp(argv[i], "-B", 2)) {      /* Print briefly */
  572.             isbrief = atoi(argv[i] + 2);/* Extract skill level */
  573.             printf("File         Map   Play  Bosses  Monsters              Weapons  Equip    RATIO\n");
  574.             printf("-------------------c-de--ba-c-s--tr-se-im-de-sp-lo-ca--cpscrpb--bvsiral-------\n");
  575.             battr = battrarry[isbrief - 1];     /* Matching attributes for
  576.                                                  * brief printout */
  577.             if (toupper(argv[i][3]) == 'M')
  578.                 battr |= 0x10;          /* Add in multi-player stuff */
  579.             continue;
  580.         }
  581.         /** Make sure at least one matching file exists **/
  582.  
  583.         if (findfirst(argv[i], &ff, FA_ARCH)) { /* No match for wildcard */
  584.             fprintf(stderr, "Can't find file matching %s\n", argv[i]);
  585.             continue;
  586.         }
  587.         /** Handle all the matching files **/
  588.  
  589.         do {
  590.             handlepwad(ff.ff_name);
  591.         } while (!findnext(&ff));
  592.     }
  593.  
  594.     /*** Return success ***/
  595.  
  596.     return 0;
  597. }
  598.  
  599. /***************************************************************************/
  600. /***************************************************************************/
  601.