home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / proglc / zoo141_c.lzh / NEXTFILE.C < prev    next >
C/C++ Source or Header  |  1987-02-07  |  9KB  |  221 lines

  1. #include "options.h"
  2. /*
  3. Copyright (C) 1986 Rahul Dhesi -- All rights reserved
  4. */
  5. /*
  6. Functions to collect filenames from command line etc.  Nextfile() is
  7. used by both Atoz and Zoo.  Wildcard expansion by nextfile() is specific to 
  8. MS-DOS and this implementation is specific to Microsoft C.  If the symbol 
  9. PORTABLE is defined, nextfile() becomes effectively a no-op that will return
  10. the original filespec the first time and NULL subsequently.
  11. */
  12.  
  13. #define  FMAX  3        /* Number of different filename patterns */
  14.  
  15. #include <stdio.h>      /* solely to define NULL */
  16. #include "various.h"
  17. #include "zoo.h"        /* solely to define PATHSIZE */
  18.  
  19. #ifdef PORTABLE
  20. #ifndef SPECNEXT
  21. /* If portable version, nextfile() is effectively a no-op and any wildcard
  22. expansion must be done by the runtime system before the command line
  23. is received by this program
  24. */
  25. char *nextfile (what, filespec, fileset)
  26. int what;                        /* whether to initialize or match      */
  27. register char *filespec;         /* filespec to match if initializing   */
  28. register int fileset;            /* which set of files                  */
  29. {
  30.    static int first_time [FMAX+1];
  31.    static char saved_fspec [FMAX+1][PATHSIZE];  /* our own copy of filespec */
  32.  
  33.    if (what == 0) {
  34.       strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
  35.       first_time[fileset] = 1;
  36.       return (NULL);
  37.    }
  38.  
  39.    if (first_time[fileset]) {
  40.       first_time[fileset] = 0;
  41.       return (saved_fspec[fileset]);
  42.    } else {
  43.       return (NULL);
  44.    }
  45. }
  46. #endif /* SPECNEXT */
  47. #else
  48. /* if not PORTABLE  then */
  49.  
  50. #include "intdos.h"     /* registers for MS-DOS interrupts              */
  51. #include "dta.h"        /* format of MS-DOS disk transfer area (dta)    */
  52. #include "assert.h"     /* macro definition:  assert() macro            */
  53.  
  54. void setdta (struct dta_t *);
  55. void fcbpath (struct dta_t *, char *, char *);
  56.  
  57.  
  58. /*******************/
  59. /*
  60. nextfile() returns the name of the next source file matching a filespec.
  61.  
  62. INPUT
  63.    what: A flag specifying what to do.  If "what" is 0, nextfile() 
  64.       initializes itself.  If "what" is 1, nextfile() returns the next 
  65.       matching filename.  
  66.    filespec:  The filespec, usually containing wildcard characters, that 
  67.       specifies which files are needed.  If "what" is 0, filespec must be 
  68.       the filespec for which matching filenames are needed.  If "what" is 1, 
  69.       nextfile() does not use "filespec" and "filespec" should be NULL to 
  70.       avoid an assertion error during debugging.
  71.    fileset:  nextfile() can keep track of more than one set of filespecs.
  72.       The fileset specifies which filespec is being matched and therefore
  73.       which set of files is being considered.  "fileset" can be in the
  74.       range 0:FMAX.  Initialization of one fileset does not affect the
  75.       other filesets.
  76.  
  77. OUTPUT
  78.    IF what == 0 THEN
  79.       return value is NULL
  80.    ELSE IF what == 1 THEN
  81.       IF a matching filename is found THEN
  82.          return value is pointer to matching filename including supplied path
  83.       ELSE
  84.          IF at least one file matched previously but no more match THEN
  85.             return value is NULL
  86.          ELSE IF supplied filespec never matched any filename THEN
  87.             IF this is the first call with what == 1 THEN
  88.                return value is pointer to original filespec
  89.             ELSE
  90.                return value is NULL
  91.             END IF
  92.          END IF
  93.       END IF
  94.    END IF
  95.  
  96. NOTE
  97.  
  98.    Initialization done when "what"=0 is not dependent on the correctness
  99.    of the supplied filespec but simply initializes internal variables
  100.    and makes a local copy of the supplied filespec.  If the supplied
  101.    filespec was illegal, the only effect is that the first time that
  102.    nextfile() is called with "what"=1, it will return the original 
  103.    filespec instead of a matching filename.  That the filespec was
  104.    illegal will become obvious when the caller attempts to open the
  105.    returned filename for input/output and the open attempt fails.
  106.  
  107. USAGE HINTS
  108.  
  109. nextfile() can be used in the following manner:
  110.  
  111.       char *filespec;                  -- will point to filespec
  112.       char *this_file;                 -- will point to matching filename
  113.       filespec = parse_command_line(); -- may contain wildcards
  114.       FILE *stream;
  115.    
  116.       nextfile (0, filespec, 0);          -- initialize fileset 0
  117.       while ((this_file = nextfile(1, NULL, 0)) != NULL) {
  118.          stream = fopen (this_file, "whatever");
  119.          if (stream == NULL)
  120.             printf ("could not open %s\n", this_file);
  121.          else
  122.             perform_operations (stream);
  123.       }
  124. */             
  125.                
  126. char *nextfile (what, filespec, fileset)
  127. int what;                        /* whether to initialize or match      */
  128. register char *filespec;         /* filespec to match if initializing   */
  129. register int fileset;            /* which set of files                  */
  130. {
  131.    static struct dta_t new_dta [FMAX+1];     /* our own private dta        */
  132.    static int first_time [FMAX+1];
  133.    static char pathholder [FMAX+1][PATHSIZE]; /* holds a pathname to return */
  134.    static char saved_fspec [FMAX+1][PATHSIZE];/* our own copy of filespec   */
  135.    union REGS regs;
  136.  
  137.    assert(fileset >= 0 && fileset <= FMAX);
  138.    if (what == 0) {
  139.       assert(filespec != NULL);
  140.       strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
  141.       first_time[fileset] = 1;
  142.       return (NULL);
  143.    }
  144.  
  145.    setdta (&new_dta[fileset]);   /* set new dta -- our very own */      
  146.    assert(what == 1);
  147.    assert(filespec == NULL);
  148.    assert(first_time[fileset] == 0 || first_time[fileset] == 1);
  149.  
  150.    if (first_time[fileset]) {             /* first time -- initialize etc. */
  151.       /* find first matching file */
  152.       regs.h.ah = 0x4e;                   /* FindFirst DOS call      */
  153.       regs.x.dx = (unsigned int) saved_fspec[fileset]; /* filespec to match */
  154.       regs.x.cx = 0;                      /* search attributes       */
  155.       intdos (®s, ®s);
  156.    } else {
  157.       /* find next matching file */
  158.       regs.h.ah = 0x4f;                   /* FindNext DOS call       */
  159.       intdos (®s, ®s);
  160.    }
  161.  
  162.    if (regs.x.carry != 0) {            /* if error status                  */
  163.       if (first_time[fileset]) {       /*   if file never matched then     */
  164.          first_time[fileset] = 0;
  165.          return (saved_fspec[fileset]);/*      return original filespec    */
  166.       } else {                         /*   else                           */
  167.          first_time[fileset] = 0;      /*                                  */
  168.          return (NULL);                /*      return (NULL) for no more   */
  169.       }
  170.    } else {                                        /* a file matched */
  171.       first_time[fileset] = 0;         
  172.       /* add path info  */
  173.       fcbpath (&new_dta[fileset], saved_fspec[fileset], pathholder[fileset]); 
  174.       return (pathholder[fileset]);                /* matching path  */
  175.    }
  176. } /* nextfile */
  177.  
  178. /*******************/
  179. /* This function sets the dta to a new dta */
  180. void setdta (dta)
  181. struct dta_t *dta;
  182. {
  183.    union REGS regs;
  184.    regs.h.ah = 0x1a;                /* SetDTA Call       */
  185.    regs.x.dx = (unsigned int) dta;  /* new DTA address   */
  186.    intdos (®s, ®s);
  187. }
  188.  
  189. /*******************/
  190. /* 
  191. fcbpath() accepts a pointer to the Disk Transfer Area (the DTA format is
  192. described on page 131 of Tandy-1000 programmers reference manual), a
  193. character pointer to a pathname that may contain wildcards, and a character
  194. pointer to a buffer.  Copies into buffer the path prefix from the pathname
  195. and the filename prefix from the DTA so that it forms a complete path
  196. */
  197.  
  198. void fcbpath (dta, old_path, new_path)
  199. struct dta_t *dta;
  200. char *old_path;
  201. register char *new_path;
  202. {
  203.    register int i;
  204.    int length, start_pos;
  205.       
  206.    strcpy(new_path, old_path);               /* copy the whole thing first */
  207.    length = strlen(new_path);
  208.    i = length - 1;                           /* i points to end of path */
  209.    while (i >= 0 && new_path[i] != '/' && new_path[i] != '\\' && new_path[i] != ':')
  210.       i--;
  211.    /* either we found a "/", "\", or ":", or we reached the beginning of
  212.       the name.  In any case, i points to the last character of the
  213.       path part. */
  214.    start_pos = i + 1;
  215.    for (i = 0; i < 13; i++)
  216.       new_path[start_pos+i] = dta->fname[i];
  217.    new_path[start_pos+13] = '\0';
  218. }
  219. #endif /* PORTABLE */
  220.  
  221.