[net.micro.amiga] getting the most out of your C disks

jdickson@jpl-milvax.arpa (04/17/86)

From: "DICKSON, JEFF S." <jdickson@jpl-milvax.arpa>

From:	 26-JUL-**** 15:12
To:	
Subj:	

	Back in November '85, someone posted a message to the effect 
that they had run their Lattice 'C' include files through some kind
of text filter and freed up a sizable amount of disk space for other
things.[:-)] 

	Well to make a long story short, that person never did make
the "fabulous filter" available to us netters [:-(]. So when I pur-
chased my Lattice 'C' compiler, I decided to write my own text filter.

	What the text filter, presented here, does to a 'C' or header
file is quite straight-forward. It basically removes all the un-
neccesary white-space characters (newlines, spaces, tabs, etc) and
comments. For some 'C' and header files, this can mean a substantial
reduction in the file's size - thus freeing up more space for your
stuff. 

	While lots of comments in any 'C' or header file are a def-
inite plus, after you've printed them out for your own personal ref-
erence - there really is no need "waste the space" on them. And let
me tell you... there are some pretty hefty include files on the 
Lattice 'C' disk. 

	This program will enable you to reclaim about 17 percent of
the space the Lattice 'C' include files currently use up. This works
out to be around 146,432 bytes or 286 blocks. 

	The command format for "pack" is as follows:

	pack [-p<pathname prefix string>] <file spec> [etc...]

	The "-p" option is used to specify the directory the filename(s) 
on the command line reside in. This is only required if you are not
already logged into that directory. 

	So, inorder to "pack" all the include files on your Lattice 'C'
disk...you would type:

	pack -pcdisk:include/  clib/*.h  libraries/*.h  workbench/*.h
exec/*.h  graphics/*.h  intuition/*.h  resources/*.h  lattice/*.h
hardware/*.h  devices/*.h

	(note: my Lattice 'C' disk is named "cdisk")

	Once started, the program will sequentially tell you which file 
is currently being packed and the number of bytes that were deleted. 
When the program is finished, the total number of bytes freed is displayed.
This is approximately the number of bytes you now have at your disposal
(+/- 511).

	The program was written to make use of the wild card expansion
routines contained in Rick Schaeffer's unix style directory utility, "wildls"
-- that was posted to the net some time ago. For the sake of completeness
and brevity, I have chosen only to included the modules from his source that
are of interest here. If you want the whole thing, it's probably available at
one of the anonymous ftp sites.

	Here are the steps for compiling and linking "pack":

	cd cdisk:
	cc1: -iinclude/ ram:pack
	cc2: ram:pack
	link: from lib/c.o+ram:pack.o+wildexp.o library lib/lc.lib+
lib/amiga.lib to ram:pack

	I recommend compiling and linking the program in ram: as it
hastens the whole process. 

	One more thing, everything compiles, links, and runs just fine
using Lattice's 'C' compiler version 3.03. Have fun!

ARPA:		JDICKSON@JPL-MILVAX
COMPUSERVE:	[76657,630]

------------------------CUT HERE--------------------------------------

/**********************************************************/
/*                                                        */
/* 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 <lattice/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);
}

--------------------END OF PACK.C---------------------------------------

/*


** The following is an include file for wildexp.c and also


** for any programs which desire to use findfirst and/or findnext.


** This file is not needed for programs that are only using


** iswild and wildexp.


**


** Written by:  Rick Schaeffer


**              E. 13611 26th Ave


**              Spokane, Wa.  99216


**              Compuserve ID: 70120,174


**              Bytenet ID: ricks.


*/





#ifndef LIBRARIES_DOS_H


#include <libraries/dos.h>


#endif





#ifndef LIBRARIES_DOSEXTENS_H


struct Msg { int dummy; };      /* make Lattice shut-up about this */


#include <libraries/dosextens.h>


#endif





/*


** The following is the structure used by findfirst and findnext.


** A pointer to this structure MUST be passed to findfirst, which


** fills it in.  Subsequent calls to findnext must pass a pointer


** to the structure which was filled in by findfirst.  The actual


** file name found is in the "fname" element of the structure after


** each call.  NOTE: The last two elements of the structure refer


** to AmigaDos specific items.  Users of findfirst and findnext may,


** if they choose, define the "find" structure such that the last


** two elements (flock and fp) are defined as "long".  In that fashion,


** you can eliminate the need to #include the "dos" information.  Of


** course, if access to the FileInfoBlock is desired, you must use


** the structure as defined below.


*/


struct find {


    char    path[128];  /* path portion of the argument */


    char    name[32];   /* name portion of the argument */


    char    fpath[128]; /* FULL path to actual file found */


                        /* NOTE: fpath is currently not filled in.  To


                           be added later */


    char    fname[32];  /* actual name of file found */


    BPTR    flock;      /* lock for the directory containing the file */


    struct FileInfoBlock *fp;   /* pointer to fib of file */


    };






/*


** The following module contains functions which permit wildcard


** filename expansion using Unix type wildcard characters.  This


** module can be compiled separately and included in the link for


** any programs which desire it's support.  The following functions


** are present:


**


**   findfirst       - find the first occurance of a file matching


**                     the given name which may contain Unix style


**                     wildcards.


**   findnext        - find the next occurance of a file.  Returns


**                     0 if no more matches remain.


**   find_cleanup    - release all storage and locks reserved by findfirst


**                     and/or findnext.  MUST be called before exit!


**   fferror         - given an error code returned by findnext, this


**                     function returns a pointer to a descriptive


**                     error message string.


**   iswild          - given a string, this function returns


**                     TRUE if the string contains a wildcard character


**                     and FALSE if not.


**   wildexp         - given a file name and a pointer to a table of


**                     pointers, this function will fill the table


**                     with a list of file names in the indicated


**                     directory which match the given name.


**


** 


** Written by:  Rick Schaeffer


**              E. 13611 26th Ave.


**              Spokane, Wa.  99216


**              Compuserve ID: 70120,174


**              Bytenet ID: ricks.


*/





#include "wildexp.h"





/*


** Return values for findfirst and findnext are:


**  0 = retval ok, find struct "fname" contains name of file found


**  1 = file name too long


**  2 = error in parsing


**  3 = invalid path name


**  4 = first Examine failed


**  5 = not a directory


*/





/* fferror -- return a meaningful error message for findxxx errors */


**  Parameter:


**     errcd - An integer containing the error code returned by findfirst


**             or findnext.


**


**  Returns:


**     msgptr - A pointer to a meaningful error message


*/


char *fferror(errcd)


int errcd;


{


    static char *errmsg[] = {


        "Filename too long",


        "Filename invalid",


        "Pathname invalid",


        "Examine failed",


        "Pathname invalid",


        "Error code invalid"


        };


    


    if (--errcd > 4)


        errcd = 5;


    return(errmsg[errcd]);


}   





/* findfirst -- find the first occurance of a given file name in either


**              the given or the current directory.


**  Parameters:


**    name - A pointer to a filename string.  May contain wildcard


**           characters ('?' and/or '*').  May optionally contain


**           a directory path.  Example: "df0:c/d*" matches all


**           files in directory "df0:c" which begin with the letter


**           "d".


**    fwk  - A pointer to a structure which will be filled in by


**           findfirst and used by findnext.  Must NOT be disturbed


**           between calls!


**


**  Returns:


**    0 = successful completion.  fwk filled in with first matching


**        file.


**   >0 = error code.  use fferror to obtain a meaningful description.


**


**  Example:


**    findfirst("*.c",fwk)


**       The first matching file is in fwk->fname.


*/


findfirst(name,fwk)


char    *name;


struct find     *fwk;


{


    struct Process *tp,*FindTask();


    int             pt[16];


    int             last;


    char            *p1,*strchr();





    fwk->fp = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),0);


        /* caller must free this space! */


    fwk->flock = 0;


    


    if (strlen(name) > 128)


        return(1); /* file name too long */


    if ((p1 = strchr(name,':')) != NULL)


        if (strchr(name,'/') == NULL) {


            *p1 = 0;


            strcpy(fwk->path,name);


            strcat(fwk->path,":/");


            strcat(fwk->path,p1+1);


            strcpy(name,fwk->path);


            }


    strcpy(fwk->path,name);


    if (stspfp(name,pt) == -1)


        return(2);  /* error in parsing */


    for (last=0; last < 16; last++)


        if (pt[last] == -1)


            break;


    last--;     /* now points at file name portion */


    if ((last == 0) && (pt[0] == 0)) {  /* no path */


        if (strlen(name) > 32)


            return(1); /* file name too long */


        strcpy(fwk->name,name);


        fwk->path[0] = 0;


        tp = FindTask(NULL);


        fwk->flock = DupLock(tp->pr_CurrentDir);


        bldfull(fwk);   /* build full path name */


        }


    else {


        if (strlen(&name[pt[last]]) > 32)


            return(1); /* file name too long */


        strcpy(fwk->name,&name[pt[last]]);


        fwk->path[pt[last] - 1] = 0;


        if ((fwk->flock = Lock(fwk->path,ACCESS_READ)) == 0)


            return(3); /* invalid path name */


        bldfull(fwk);


        }


    if (Examine(fwk->flock,fwk->fp)) {  /* get directory name */


        if (fwk->fp->fib_DirEntryType > 0)


            return(findnext(fwk));


        else


            return(5); /* not a directory */


        }


    else


        return(4);  /* first examine failed */


}





/*


** findnext -- find next occurance of a matching file.


**  Parameter:


**    fwk - pointer to a "find" structure which has been filled in


**          by a call to findfirst.


**


**  Returns:


**    0 = Match found.  fwk->fname contains the name.


**   -1 = No more matches.


*/


int findnext(fwk)


struct find *fwk;


{


    while (ExNext(fwk->flock,fwk->fp)) {


        strcpy(fwk->fname,fwk->fp->fib_FileName);


        if (fnmatch(fwk->fname,fwk->name))


            return(0);


        }


    return(-1);


}





bldfull()


{


}





/* find_cleanup -- release any structures and locks used by findfirst.


**   Parameters:


**      fwk - pointer to a "find" structure which has been previously


**            filled in by findfirst.


**   Returns:


**    nothing


*/


find_cleanup(fwk)


struct find *fwk;


{


    if (fwk->flock)


        UnLock(fwk->flock);


    if (fwk->fp)


        FreeMem(fwk->fp,sizeof(struct FileInfoBlock));


}





/* fnmatch -- perform unix style pattern match on a file name


**   usage: result = fnmatch(name,pattern)


**       returns 1 if "name" matches "pattern", 0 otherwise


*/





int fnmatch(name,pattern)


register char   *name,*pattern;


{





    while (*pattern) {


        if (*pattern == '*') {


            while (*pattern == '*')


                pattern++;


            while ((*name) && (tolower(*name) != tolower(*pattern)))


                name++;


            if (*name == 0)


                if (*pattern == 0)


                    return(1);  /* matched */


                else


                    return(0);


            }


        if (*pattern == '?') {


            pattern++;


            name++;


            continue;


            }


        if (tolower(*pattern) != tolower(*name))


            return(0); /* not matched */


        pattern++;


        name++;


        }


    if ((*name == 0) && (*pattern == 0))


        return(1);  /* matched */


    else


        return(0);  /* not matched */


}





/*


** wildexp -- expand a wildcard file name


**  Parameters:


**    name     - Pointer to the file name to be expanded.


**    adtbl    - Pointer to an array of pointers.


**    maxargs  - The maximum number of pointers contained in adtbl.


**


**  Returns:


**    1 = Successful completion.  The adtbl array will contain pointers


**        to all file names found and will be terminated with a NULL


**        pointer.  It's use is exactly like use of the standard C


**        argv array except that the first filename argument is in


**        adtbl[0] whereas argv[0] contains a pointer to the name of


**        the function which was invoked.


**    0 = An error occured.


*/


int wildexp(name,adtbl,maxargs)


char            *name;


register char   **adtbl;


int             maxargs;


{


    struct find f;


    register int i=0;


    char        *malloc();


    int     retval;





    if ((retval = findfirst(name,&f)) > 0) {


        *adtbl = NULL;


        find_cleanup(&f);


        return(0);


        }


    while (retval == 0) {


        if (f.fp->fib_DirEntryType > 0) {


            retval=findnext(&f);


            continue;   /* it's a directory */


            }


        *adtbl = malloc(strlen(f.path)+strlen(f.fname)+1);


        if (*adtbl == NULL) {


            find_cleanup(&f);


            return(0);  /* arena is full */


            }


        strcpy(*adtbl,f.path);


        if ((f.path[0] != 0) && (f.path[strlen(f.path)-1] != ':'))


            strcat(*adtbl,"/");


        strcat(*adtbl++,f.fname);


        if ((++i) >= maxargs)


            return(0);


        retval=findnext(&f);


        }


    *adtbl = NULL;


    find_cleanup(&f);


    return(1);


}





int iswild(s)


char    *s;


{


    while (*s) {


        if ((*s == '*') || (*s == '?'))


            return(1);


        s++;


        }


    return(0);


}


------