/**********************************************************/
/*                                                        */
/* This program accepts a list of C source or header files*/
/* and filters out all the comments and unneccesary white */
/* space characters--thereby, reducing the overall file   */
/* size and increasing the amount of user usable disk     */
/* space.                                                 */
/*                                                        */
/* Written by, Jeff S. Dickson, April 9, 1986             */
/* Feel free to distribute it to anyone who is interested */
/* in reclaiming desperately needed disk space.           */
/**********************************************************/


#include <stdio.h>
#include "wildexp.h"

#define NULFILPNTR   ((FILE *)0)

#define MAXPREFIXLEN 32

main(argc, argv)

int argc;
char *argv[];
{

    char filename[128];
    char pathname[128];
    char prepend_str[128];
    char temp[128];

    int c;
    int i;
    int j;
    int len;
    int newlen;
    int maxitems;
    int Slash = FALSE;
    int Asterik = FALSE;
    int Comment = FALSE;
    int WhiteSpace = FALSE;
    int NewLine = FALSE;
    int CharsRead;
    int CharsWritten;
    int Chars2rewrite;
    int TotalChars = 0;

    FILE *sfp, *tfp, *lfp;


    /* verify that the correct number of args were specified */

    if (argc == 1) {
       printf("Insufficient Arguments\n\n");
       printf("Usage: pack [-p<pathname prefix string>] <file spec> [etc...]\n");
       exit();
    }

    /* open the scratch files */

    if ((lfp = fopen("ram:listfile", "w+")) == NULFILPNTR) {
       printf("pack: Can't create list file\n");
       exit();
    }
    if ((tfp = fopen("ram:tempfile", "w+")) == NULFILPNTR) {
       printf("pack: Can't create sratch file\n");
       fclose(lfp);
       unlink("ram:listfile");
       exit();
    }

    /* check if the user specifed a directory specification */
    /* to be prepended to filenames                         */

    if (strncmp(*(argv + 1), "-p", 2) == 0) {
       strncpy(prepend_str, *++argv + 2, MAXPREFIXLEN);
       --argc;
    }
    else
       prepend_str[0] = '\0';
    len = strlen(prepend_str);

    /* main loop -- take the current arg, generate a list of */
    /* files that could possibly correspond to it, and cond- */
    /* ence them                                             */

    for (; argc != 1; argc--) {
       prepend_str[len] = '\0';
       strncpy(temp, *++argv, sizeof (temp));
       for (i = j = 0; temp[i] != '\0'; i++)
           if (temp[i] == '/' || temp[i] == ':')
               j = i + 1;

       if ((newlen = len + j) > sizeof (prepend_str)) {
           printf("Can't do %s - argument too long\n",temp);
           continue;
       }
       strncat(prepend_str, temp, j);
       strcpy(filename, prepend_str);
       if (strlen(&temp[j]) + newlen > sizeof (filename)) {
           printf("Can't do %s - argument too long\n",temp);
           continue;
       }
       strcat(filename, &temp[j]);

       rewind(lfp);
       maxitems = makelist(filename, lfp);
       rewind(lfp);

       while ((fgets(filename, sizeof (filename) - newlen,
               lfp) != (char *)0) && (maxitems-- != 0)) {
          filename[strlen(filename) - 1] = '\0';
          strcpy(pathname, prepend_str);
          strcat(pathname, filename);
          if ((sfp = fopen(pathname, "r+")) == NULFILPNTR) {
             printf("pack: Can't open %s\n", pathname);
             continue;
          }
          rewind(tfp);
          printf("Condensing %s ====> ", pathname);
          CharsRead = 0;
          CharsWritten = 0;
          while ((c = getc(sfp)) != EOF) {
             ++CharsRead;
             if (!(Comment)) {
                switch(c) {
                   case '/' : if (Slash) {
                                 ungetc(c, sfp);
                                 Slash = FALSE;
                                 break;
                              }
                              Slash = TRUE;
                              continue;
                   case '*' : if (Slash) Comment = TRUE;
                              else break;
                              continue;      
                   case ' ' :
                   case '\t': if (!(WhiteSpace)) {
                                 WhiteSpace = TRUE;
                                 break;
                              }
                              continue;
                   case '\n': if (!(Slash)) {
                                 if (!(NewLine)) {
                                    NewLine = TRUE;
                                    WhiteSpace = TRUE;
                                    break;
                                 }
                                 else continue;
                              }
                   default  : if (Slash) {
                                 ungetc(c, sfp);
                                 c = '/';
                              }
                              NewLine = FALSE;
                              WhiteSpace = FALSE;
                              Slash = FALSE;
                }
                putc(c, tfp);
                ++CharsWritten;
             }
             else
             {
                switch(c) {
                   case '/' : if (Asterik) {
                                 Comment = FALSE;
                                 Slash = FALSE;
                                 Asterik = FALSE;
                              }
                              break;
                   case '*' : Asterik = TRUE;
                              break;
                   default  : Asterik = FALSE;
                }
             }
          }                     
          if ((sfp = freopen(pathname,"w", sfp)) == NULFILPNTR)
             printf("pack: Error Re-opening %s for rewrite\n", pathname);
          else
          {
             rewind(tfp);
             for (Chars2rewrite = 0; Chars2rewrite < CharsWritten; Chars2rewrite++) {
                 if ((c = getc(tfp)) == EOF)
                    break;
                 putc(c, sfp);
             }
             printf("\rThere are now %6d less characters in %s\n",(CharsRead - CharsWritten), pathname);
             TotalChars += (CharsRead - CharsWritten);
          }
          fclose(sfp);
       }
    }
    printf("\nTotal character(s) removed %d\n", TotalChars);
    fclose(tfp);
    fclose(lfp);
    unlink("ram:tempfile");
    unlink("ram:listfile");
}

/* this function makes use of the routines written by Rick */
/* Schaeffer [CPS 70120,124] to construct a list of all    */
/* possible files that correspond to the passed filename   */

int makelist(pattern, list)

char *pattern;
FILE *list;
{
   int retval;
   int NumberOfItems= 0;
   int search4first = TRUE;

   struct find fwk;

   for (;;) {
      if (search4first) {
         if ((retval = findfirst(pattern, &fwk)) != 0)
            break;
      }
      else if ((retval = findnext(&fwk)) < 0)
         break;

      fputs(fwk.fname, list);
      fputc('\n', list);
      ++NumberOfItems;
      search4first = FALSE;
   }
   find_cleanup(&fwk);
   return(NumberOfItems);
}
