/*
* The purpose of this program is to build parameter lists
* for programs such as the SQ and USQ file compression
* utilities. This and those programs use the directed io
* package to allow redirection of console input and/or output.
* They are coded to accept parameters from the console input or
* from the command line. Each parameter is on a seperate line.
*
* Names beginning with '-' are passed through as options.
* Drive names (with ':') alone are also passed through.
*
* Other parameters are treated as ambiguous file names with
* optional drive specification. The disk directory is searched
* and every specific file name which matches the pattern is
* sent to the output list (with the optional drive specifier).
* If there are no matches a comment is sent to the console.
*
* Example test run (output to console):
*      A>fls *.c c:*.com b: *.h
* Example to build list in "file":
*      A>fls *.c c:*.com b: *.h >file
* Example to build list in file and send to console too:
*      A>fls *.c c:*.com b: *.h +file
* Example to build list and run program SQ.COM with list
* substituting for keyboard input:
*      A>fls b: *.c d:*.?Q? |sq
*/

#define VERSION "1.1   06/16/81"
#define STDERR  4       /* Error output stream (always console) */

#include <bdscio.h>
#include <dio.h>

#define SRCH 17 /*bdos search for file pattern*/
#define SRCHNXT 18
#define SETDMA 26
#define TBUFF (0x80+BASE)       /*default disk buffer*/

struct fcb {            /* File control block */
       char xxx[36];   /* enough for CP/M 2 */
};


main(argc, argv)
int argc;
char *argv[];
{
       int i,c;
       int getchar();          /* Directed io version */
       int putchar();          /* Directed io version */
       char inparg[16];        /* parameter from input */

       dioinit(&argc, argv);   /* obey directed to args */

       fprintf(STDERR, "Parameter list builder - Version %s by\n\tRichard Greenlaw\n\t251 Colony Ct.\n\tGahanna, Ohio 43230\n", VERSION);
       fprintf(STDERR, "Accepts redirection and pipes.\nOmit other parameters for help and prompt\n\n");

       /* Process the parameters in order */
       for(i = 1; i < argc; ++i)
               obey(argv[i]);

       if(argc < 2) {
               fprintf(STDERR, "\nParameters are from command line or (singly) from console input.\n");
               fprintf(STDERR, "Drive names and -options are passed thru.\nAmbiguous file names are expanded. CR or EOF to stop.\n");
               do {
                       fprintf(STDERR, "\n*");
                       for(i = 0; i < 16; ++i) {
                               if((c = getchar()) == EOF)
                                       c = '\n';       /* fake empty (exit) command */
                               if((inparg[i] = c) == '\n') {
                                       inparg[i] = '\0';
                                       break;
                               }
                       }
                       if(inparg[0] != '\0')
                               obey(inparg);
               } while(inparg[0] != '\0');
       }
       dioflush();     /* clean up any directed io */
}

/*
* Function to convert an input parameter to a list of
* output parameters. Drives (d:), options (-string) and
* specific file names (w/ optional drive) are passed through.
* Ambiguous file names are expanded (w/ optional drive)
* or, if not found, are ignored with comment.
*
* Any parameter beginning with a '-' and drive: alone
* are simply passed to the output.
*
* Results are sent to standard output (presumably redirected)
* with one output parameter per line.
*/

obey(afnp)
char *afnp;     /* possible ambiguous file name*/
{
       struct fcb sfcb;
       char *p, *q, i, byteaddr;
       int     n;
       char ufn[15];   /* unambiguous file name */

       if(*afnp == '-' || (*(afnp + 1) == ':' && *(afnp + 2) == '\0'))
               printf("%s\n", afnp);   /* pass through option or drive */
       /* Try to build CP/M FCB */
       else if(setfcb(&sfcb, afnp) == ERROR)
               fprintf(STDERR, "%s is bad afn\n", afnp);
       else {
               /* Search disk directory for all ufns which match afn*/
               for(n = 0; ; ++n) {
                       bdos(SETDMA, TBUFF);
                       byteaddr = n ? bdos(SRCHNXT,&sfcb) : bdos(SRCH,&sfcb);
                       if(byteaddr == 255)
                               break;
                       p = ufn;
                       if(*(afnp+1) == ':') {
                               /* Drive spec.*/
                               *p++ = *afnp;
                               *p++ = ':';
                       }

                       /*Copy filename from directory*/
                       q = TBUFF + 32 * (byteaddr % 4);
                       for(i =8; i; --i)
                               if((*p = 0x7F & *++q) != ' ') ++p;
                       *p++ = '.' ;

                       /*Copy file extent*/
                       for(i = 3; i; --i)
                               if((*p = 0x7F & *++q) != ' ') ++p;
                       *p = '\0' ;

                       /* Output result */
                       printf("%s\n", ufn);
               }
               if(n == 0)
                       fprintf(STDERR, "%s not found - ignored\n", afnp);
       }
}