/***************************************************************************
 *                                                                         *
 *   GALMKLST.C                                                            *
 *                                                                         *
 *   Copyright (c) 1994-1997 Galacticomm, Inc.  All rights reserved.       *
 *                                                                         *
 *   Based on user input, read a catalog file and produce a list of files  *
 *   This is based on GETLST.C                                             *
 *                                                - W. Muharsky 07/21/97   *
 *                                                                         *
 ***************************************************************************/
#include "gcomm.h"

#define FILREV "$Revision: 4 $"

VOID help(VOID);
INT parse(CHAR *argv);
INT prscat(VOID);
VOID iskeyw(CHAR *key);
VOID outfile(CHAR *outstr);
INT pcmtch(CHAR *inp,CHAR *wild);
INT cmtch(CHAR c, CHAR pc);
INT isnot(CHAR *key);

#define FILEDEF "GETLST.LST"       /* Default output filename              */
#define MAXKEYL (8+1)              /* Define maximum key length            */
#define MAXKEYN 64                 /* Define maximum number of keys        */
#define MAXORS 32                  /* Define maximum number of OR's        */
#define CAT1 ""                    /* catalog location                  */
#define ALLFILES "*.*"             /* Default file search string           */
#define BUFFER 32000               /* Buffer size for output file          */

INT numkey=0,                      /* Number of keywords                   */
    catlines=0,                    /* Current catalog line number          */
    cotlines=0,                    /* Current .lst line output             */
    pathflag=0,                    /* Path in command line flag            */
    fileflag=0,                    /* Set if there was a /F directive      */
    numlst=0,                      /* Number of keyword lists              */
    lstflg[MAXORS][MAXKEYN];       /* Kwyword flags                        */

CHAR keylist[MAXORS][MAXKEYN][MAXKEYL], /* Keyword array                   */
     filespec[MAXPATH],            /* File specification                   */
     catbuf[BUFSIZ],               /* Catalog I/O buffer                   */
     ofile[MAXPATH],               /* Output filelist                      */
     catfilen[MAXPATH];            /* Filename and path from catalog file  */

CHAR *devenv,                      /* Development environment              */
     *buffer,                      /* Buffer for output file               */
     *catfile;                     /* catalog file name                    */

FILE *out,                         /* Output file                          */
     *cat;                         /* Catalog file                         */

GBOOL nopath=FALSE;                /* If true, no path info in list        */

INT
main(                              /* Main program loop                    */
INT argc,                          /*   Number of command line arguments   */
CHAR *argv[])                      /*   List of command line arguments     */
{
     INT i,x;

     initvid();
     setatr(0x0E);
     setmem(ofile,sizeof(ofile),0);
     setmem(filespec,sizeof(filespec),0);
     setmem(keylist,sizeof(keylist),0);
     setmem(catfilen,sizeof(catfilen),0);
     if (argc <= 1) {
          help();
          clsvid();
          return(1);
     }
     printf("\nGALMKLST - Processing file...\n");
     printf("          (hit Esc to abort)\n\n");
     catfile=CAT1;
     for(i=1 ; i < argc ; i++) {
          if (parse(argv[i]) == 1) {
               catastro(spr("Command parse error: %s\n",argv[i]));
          }
     }
     if ((devenv=getenv("WGDEV")) == NULL) {
          catastro("Unable to read WGDEV Environment variable!");
     }

     buffer=alcmem(BUFFER);
     if (ofile[0] == '\0') {
          stzcpy(ofile,FILEDEF,MAXPATH);
     }
     if ((out=fopen(ofile,FOPWB)) == NULL) {
          catastro(spr("Error: Cannot open %s",ofile));
     }
     setvbuf(out,buffer,_IOFBF,BUFFER);
     if ((cat=fopen(catfile,FOPRA)) == NULL) {
          catastro("Unable to open catalog file!");
     }
     x=0;
     cursiz(GVIDNOCURS);
     printf(" %d -> %d     \r",catlines,cotlines);
     while ((fgets(catbuf,BUFSIZ,cat)) != NULL) {
          if (kbhit() && getchc() == ESC) {
               setatr(0x0C);
               printf("\nGALMKLST: User abort!\n");
               setatr(0x07);
               printf("\r");
               break;
          }
          catlines++;
          if ((x != cotlines) || ((catlines%37) == 0)) {
               printf(" %d -> %d     \r",catlines,cotlines);
               x=cotlines;
          }
          if (prscat()) {
               catastro(spr("Error in file, line %d.\n",catlines));
          }
     }
     printf(" %d -> %d     \r",catlines,cotlines);
     fclose(out);
     fclose(cat);
     cursiz(GVIDLILCURS);
     clsvid();
     return(0);
}

INT
parse(                             /* Command line parser                  */
CHAR *arg)                         /*   Argument to parse                  */
{
     INT retval=0;
     CHAR fnam[GCMAXPTH];
     CHAR *ptr;

     ASSERT(arg > NULL);
     switch (arg[0]) {
     case '/':
          switch (toupper(arg[1])) {
          case 'F':
               fileflag=1;
               stzcpy(filespec,&arg[2],MAXPATH);
               retval=0;
               fileparts(GCPART_FNAM,filespec,fnam,GCMAXPTH);
               if (sameas(filespec,fnam)) {
                    pathflag=1;
               }
               else {
                    pathflag=0;
               }
               break;
          case 'C':
               catfile=alcdup(&arg[2]);
               retval=0;
               break;
          case 'O':
               stzcpy(ofile,&arg[2],MAXPATH);
               retval=0;
               break;
          case 'P':
               nopath=TRUE;
               break;
          default:
               retval=1;
               break;
          }
          break;
     default:
          for (ptr=firstwd(arg); *ptr != '\0'; ptr=nextwd()) {
               if (sameas(ptr,"OR")) {
                    numlst++;
                    numkey=0;
                    retval=0;
               }
               else {
                    stzcpy(keylist[numlst][numkey++],ptr,MAXKEYL);
                    retval=0;
               }
          }
          break;
     }
     return(retval);
}

INT
prscat(VOID)                       /* Parse catalog file input             */
{
     CHAR fnam1[GCMAXPTH],fnam2[GCMAXPTH];
     CHAR *ptr,*gtr,*src,*dest,cattmp[BUFSIZ],tmpstr[MAXKEYL],wrkstr[BUFSIZ];
     INT cnt,i,j,match,ineed,igot,done;

     if (catbuf[strlen(catbuf)-1] != '\n') {
          strcat(catbuf,"\n");
     }
     if (catbuf[0] == ';') {
          return(0);
     }
     if ((ptr=strchr(catbuf,';')) != NULL) {
          *ptr='\n';
          *(ptr+1)='\0';
     }
     stzcpy(cattmp,catbuf,BUFSIZ);
     if ((gtr=strchr(cattmp,' ')) != NULL) {
          *gtr='\0';
     }
     if (fileflag) {
          if (!pathflag) {
               fileparts(GCPART_PATH,cattmp,fnam1,GCMAXPTH);
               fileparts(GCPART_PATH,filespec,fnam2,GCMAXPTH);
               if (!sameas(fnam1,fnam2)) {
                    return(0);
               }
          }
     }
     setmem(catfilen,sizeof(catfilen),0);
     src=catbuf;
     for (cnt=0 ; !isspace(*src) ; cnt++,src++) {
          wrkstr[cnt]=*src;
     }
     wrkstr[cnt]='\0';
     stzcpy(catfilen,wrkstr,MAXPATH);
     for (i=0 ; i < MAXORS ; i++) {
          for (j=0 ; j < MAXKEYN ; j++) {
               lstflg[i][j]=0;
          }
     }
     done=0;
     while (!done) {
          dest=skpwht(src);
          if (*dest == '\n') {
               done=1;
          }
          else {
               for (cnt=0 ; !isspace(*dest) && *dest != '\n' ;
                                    cnt++,dest++) {
                    tmpstr[cnt]=*dest;
               }
               tmpstr[cnt]='\0';
               iskeyw(tmpstr);
               src=dest;
          }
     }
     match=0;
     for (i=0 ; i < MAXORS ; i++) {
          ineed=0;
          igot=0;
          for (j=0 ; j < MAXKEYN ; j++) {
               if (keylist[i][j][0] != '\0') {
                    ineed++;
                    if (isnot(keylist[i][j])) {
                         lstflg[i][j]=!lstflg[i][j];
                    }
                    if (lstflg[i][j] == 1) {
                         igot++;
                    }
               }
          }
          if (ineed > 0) {
               if (ineed == igot) {
                    match=1;
                    break;
               }
          }
     }
     if (match) {
          if (!fileflag) {
               outfile(catfilen);
          }
          else {
               fileparts(GCPART_FNAM,catfilen,fnam1,GCMAXPTH);
               fileparts(GCPART_FNAM,filespec,fnam2,GCMAXPTH);
               if (pcmtch(fnam1,fnam2)) {
                    outfile(catfilen);
               }
          }
     }
     return(0);
}

VOID
iskeyw(                            /* Check to see if keyword in list      */
CHAR *key)                         /*   Keyword to check                   */
{
     INT i,j,notkey;

     for (i=0 ; i < MAXORS ; i++) {
          for (j=0 ; j < MAXKEYN ; j++) {
               if (keylist[i][j][0] != '\0') {
                    notkey=isnot(keylist[i][j]);
                    if (sameas(key,notkey ? &keylist[i][j][1]
                                          : keylist[i][j])) {
                         lstflg[i][j]=1;
                    }
               }
          }
     }
}

VOID
outfile(                           /* Outputs string to list file          */
CHAR *outstr)                      /*   String to output                   */
{
     CHAR *ptr;

     cotlines++;
     if (nopath) {
          ptr=strrchr(outstr,'\\');
          fprintf(out,"%s\r\n",++ptr);
     }
     else {
          if (pathflag || !fileflag) {
               fprintf(out,"%s\r\n",outstr);
          }
          else {
               ptr=strrchr(outstr,'\\');
               fprintf(out,"%s\r\n",++ptr);
          }
     }
}

VOID
help(VOID)                         /* Program help                         */
{
     printf("\n\007");
     printf("Usage: GALMKLST /C<Catfile> [/P] [/FFspc] [/OOutf] ");
     printf("[!]Key [[or ][!]Key]...] \n");
     printf("\n");
     printf("     /P      Inhibits ANY path information to Outf\n");
     printf("     /C      Specify file to search through\n");
     printf("     Catfile Name of the file to search through\n");
     printf("     /F      Required if a Fspc is used\n");
     printf("     Fspc    Filename or specification (i.e. wildcard)\n");
     printf("     /O      Force output to a file\n");
     printf("     Outf    Output filename (default: GETLST.LST)\n");
     printf("     or      Seperates lists of keywords\n");
     printf("     !       Indicates a keyword should not be present\n");
     printf("     Key     Catalog keyword to process\n");
     printf("\n");
}

INT
pcmtch(                            /* Compare filename to wild one         */
CHAR *input,                       /*   A regular filename                 */
CHAR *picstg)                      /*   A wild card                        */
{
     CHAR c,pc,*lanypc=NULL,*lanyin;

     while ((c=*input++) != '\0') {
          if ((pc=*picstg++) == '*') {
               while ((pc=*picstg) == '*') {
                    picstg++;
               }
               while (!cmtch(c,pc)) {
                    if (c == '\0') {
                         return(0);
                    }
                    c=*input++;
               }
               lanypc=picstg-1;
               lanyin=input;
               input--;
          }
          else {
               if (!cmtch(c,pc)) {
                    if (lanypc != NULL) {
                         picstg=lanypc;
                         input=lanyin;
                    }
                    else {
                         return(0);
                    }
               }
          }
     }
     while (*picstg == '*') {
          picstg++;
     }
     return(*picstg == '\0');
}

INT
cmtch(                             /* Compare character to ?               */
CHAR c,
CHAR pc)
{
     switch (pc) {
     case '?':                        /* any-char */
          return(1);
     default:
          return(tolower(c) == tolower(pc));
     }
}

INT
isnot(                             /* Is this key a not key?               */
CHAR *key)                         /*   Key to check                       */
{
     if (key[0] == '!') {
          return(1);
     }
     return(0);
}
