home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / compress / zoosrc20.zoo / nextfile.c < prev    next >
C/C++ Source or Header  |  1989-07-25  |  9KB  |  228 lines

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