595 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			595 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//
 | 
						|
// WILDCARD.CPP
 | 
						|
//
 | 
						|
//  Source file for ArchiveLib 1.0
 | 
						|
//
 | 
						|
//  Copyright (c) Greenleaf Software, Inc. 1994
 | 
						|
//  All Rights Reserved
 | 
						|
//
 | 
						|
// CONTENTS
 | 
						|
//
 | 
						|
//  ALWildCardExpander::operator new()
 | 
						|
//  ALWildCardExpander::ALWildCardExpander()
 | 
						|
//  ALWildCardExpander::~ALWildCardExpander()
 | 
						|
//  ALWildCardExpander::GetNextWildName()
 | 
						|
//  ALWildCardExpander::GetNextFile()
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This file contains all the source code for the nifty class
 | 
						|
//  ALWildCardExpander.  The wild card expansion code is a state
 | 
						|
//  drive routine, which keeps track of its entire state between
 | 
						|
//  calls.  So you can call it once to get a new file name, then
 | 
						|
//  do some processing.  When you call it again later, you will
 | 
						|
//  get the next file name in the sequence.
 | 
						|
//
 | 
						|
//  There is a little difference between the NT version and the DOS
 | 
						|
//  version, because the function calls for get first/get next
 | 
						|
//  are different.  A minor difference is created by the fact
 | 
						|
//  that under NT you can't specify attributes in a search, so when
 | 
						|
//  you want to look for subdirectories, you have to search all files
 | 
						|
//  and see if any of your matches turn out to be directories.
 | 
						|
//
 | 
						|
//  The way the wild card class handles searching through subdirectories
 | 
						|
//  is by keeping a link pointer to a subdirectory search.  When it 
 | 
						|
//  is time to open up a subdirectory search, we create a new file
 | 
						|
//  expander, and assign its pointer to our link pointer.  As long as
 | 
						|
//  the link is active, we keep searching there.  When the link runs
 | 
						|
//  out of files to return, we continue searching in our own directory.
 | 
						|
//
 | 
						|
//  A lot of this code is easier to deal with because we use the
 | 
						|
//  ALName class.  That makes it easy to strip file names and
 | 
						|
//  paths apart, and even easier to put them back together again.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//  May 26, 1994  1.0A  : First release
 | 
						|
//
 | 
						|
//
 | 
						|
 | 
						|
#include "arclib.h"
 | 
						|
#pragma hdrstop
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#ifdef __BORLANDC__
 | 
						|
#include <dir.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "wildcard.h"
 | 
						|
 | 
						|
//
 | 
						|
// void * ALWildCardExpander::operator new( size_t size )
 | 
						|
//
 | 
						|
// ARGUMENTS:
 | 
						|
//
 | 
						|
//  size  :  The number of bytes needed to create a new ALWildCardExpander
 | 
						|
//           object.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  A pointer to the newly allocated storage area, or 0 if no storage
 | 
						|
//  was available.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  When using a DLL, it is easy to get into a dangerous situation when 
 | 
						|
//  creating objects whose ctor and dtor are both in the DLL.  The problem
 | 
						|
//  arises because when you create an object using new, the memory for
 | 
						|
//  the object will be allocated from the EXE.  However, when you destroy
 | 
						|
//  the object using delete, the memory is freed inside the DLL.  Since
 | 
						|
//  the DLL doesn't really own that memory, bad things can happen.
 | 
						|
//
 | 
						|
//  But, you say, won't the space just go back to the Windows heap regardless
 | 
						|
//  of who tries to free it?  Maybe, but maybe not.  If the DLL is using 
 | 
						|
//  a subsegment allocation scheme, it might do some sort of local free
 | 
						|
//  before returning the space to the windows heap.  That is the point where
 | 
						|
//  you could conceivably cook your heap.
 | 
						|
//
 | 
						|
//  By providing our own version of operator new inside this class, we
 | 
						|
//  ensure that all memory allocation for the class will be done from
 | 
						|
//  inside the DLL, not the EXE calling the DLL.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   May 26, 1994  1.0A  : First release
 | 
						|
//
 | 
						|
 | 
						|
#if defined( AL_BUILDING_DLL )
 | 
						|
void AL_DLL_FAR * AL_PROTO ALWildCardExpander::operator new( size_t size )
 | 
						|
{
 | 
						|
    return ::new char[ size ];
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
//
 | 
						|
// ALWildCardExpander::ALWildCardExpander( const char *file_list,
 | 
						|
//                                         int traverse_flag = 0,
 | 
						|
//                                         ALCase name_case = AL_LOWER ) 
 | 
						|
//
 | 
						|
// ARGUMENTS:
 | 
						|
//
 | 
						|
//  file_list       : A list of wild card file specifications, separated
 | 
						|
//                    by commas, semicolons, or spaces, maybe looking 
 | 
						|
//                    something like this: "*.CPP, BOB.DAT, *.*"
 | 
						|
//
 | 
						|
//  traverse_flag   : A flag that indicates whether you want to traverse
 | 
						|
//                    all subdirectories under the current path.
 | 
						|
//
 | 
						|
//  name_case       : An indicator of whether you want all the returned
 | 
						|
//                    file names forced to a certain case.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  No returns.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  The constructor for the expander has to set up a bunch of data members
 | 
						|
//  that will all be used during the expansion process.  The mCase
 | 
						|
//  member is easy to understand.  All of the objname objects that
 | 
						|
//  we create are going to be force to a certain case by this
 | 
						|
//  using this data member.  miTraverseFlag is just our copy of the
 | 
						|
//  input parameter.  And the mState variable keeps track of what we
 | 
						|
//  are doing in between function calls.  We set it to GET_NEXT_WILD_NAME,
 | 
						|
//  which means we will be doing that the first time we get called.
 | 
						|
// 
 | 
						|
//  mInputLine is where we keep a copy of the list of wild card file
 | 
						|
//  specifications passed by the calling program.  Each time we take
 | 
						|
//  a new file name out of mInputLine, we remove it from the ALName
 | 
						|
//  object, making mInputLine just a little shorter.
 | 
						|
//
 | 
						|
//  The mResultFileName member is the storage area where we keep a copy
 | 
						|
//  of the file name created by the expander.  This is our local copy,
 | 
						|
//  when it gets returned to the calling program they need to make
 | 
						|
//  their own copy of it and leave ours alone.
 | 
						|
//
 | 
						|
//  Every time we get asked to get a new file, the very first thing
 | 
						|
//  we do is check to see if the mpNextExpander member is pointing
 | 
						|
//  to a new expander object.  If it is, we ask him to provide
 | 
						|
//  the next file name, instead of giving it ourselves.  When he
 | 
						|
//  doesn't have any file names left to give, we destroy him and
 | 
						|
//  set that pointer back to 0.  Here in the constructor, the smart
 | 
						|
//  thing to do is set him to 0 for starters.
 | 
						|
//
 | 
						|
//  The final data member differs between NT and DOS.  The structure
 | 
						|
//  NT uses to expand directories is store in mFindFileHandle.  The
 | 
						|
//  DOS version is stored in mpFfblk.  Both of these are presently
 | 
						|
//  in an invalid state, but will get initialized when the user
 | 
						|
//  calls the member function.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   May 26, 1994  1.0A  : First release
 | 
						|
//
 | 
						|
 | 
						|
AL_PROTO ALWildCardExpander::ALWildCardExpander(
 | 
						|
          const char AL_DLL_FAR *file_list,
 | 
						|
          int traverse_flag /* = 0 */,
 | 
						|
          ALCase name_case /* = AL_LOWER */ ) 
 | 
						|
    : mCase( name_case ), 
 | 
						|
      mResultFileName( "", name_case )
 | 
						|
{
 | 
						|
    mInputLine = file_list;
 | 
						|
    mState = GET_NEXT_WILD_NAME;
 | 
						|
    mpNextExpander = 0;
 | 
						|
    miTraverseFlag = traverse_flag;
 | 
						|
#if defined( AL_WIN32S ) 
 | 
						|
    mFindFileHandle = INVALID_HANDLE_VALUE;
 | 
						|
#else
 | 
						|
    mpFfblk = new find_t;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// ALWildCardExpander::~ALWildCardExpander()
 | 
						|
//
 | 
						|
// ARGUMENTS:
 | 
						|
//
 | 
						|
//  None, destructors don't get any.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  None, destructor.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  There are a couple of big deals we need to worry about in the
 | 
						|
//  destructor an ALWildCardExpander.  First, we have to worry about
 | 
						|
//  any additional handlers we created to search subdirectories.  If
 | 
						|
//  this destructor is being called before our search is done, we
 | 
						|
//  may have some of those expander objects just hanging around out
 | 
						|
//  there.  We take care of the by checking the mpNextExpander member.
 | 
						|
//  If it isn't set to 0, we delete the dynamically created expander.
 | 
						|
//
 | 
						|
//  Under NT we also have to worry about our mpFindFileHandle.  Under
 | 
						|
//  NT, the file expansion algorithm isn't just a get first/get next
 | 
						|
//  deal.  Instead, it is get first/get next/terminate.  The termination
 | 
						|
//  is done using the FindClose() call.  If we still had a search in progress
 | 
						|
//  we call that function.
 | 
						|
//
 | 
						|
//  Under DOS, we just have to delete the dynamically created
 | 
						|
//  mpFfblk structure.  I wanted to make that a data member of this
 | 
						|
//  class, instead of a pointer, but one of our compilers wasn't happy
 | 
						|
//  about putting this C struct in a class, it complained about something.
 | 
						|
//  So, to expedite, we made it a pointer.
 | 
						|
//
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   May 26, 1994  1.0A  : First release
 | 
						|
//
 | 
						|
 | 
						|
AL_PROTO ALWildCardExpander::~ALWildCardExpander()
 | 
						|
{
 | 
						|
    if ( mpNextExpander )
 | 
						|
        delete mpNextExpander;
 | 
						|
#if defined( AL_WIN32S )
 | 
						|
    if ( mFindFileHandle != INVALID_HANDLE_VALUE )
 | 
						|
        FindClose( mFindFileHandle );
 | 
						|
#else
 | 
						|
    if ( mpFfblk )
 | 
						|
        delete mpFfblk;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
// PROTECTED MEMBER FUNCTION
 | 
						|
//
 | 
						|
// int ALWildCardExpander::GetNextWildName()
 | 
						|
//
 | 
						|
// ARGUMENTS:
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  1 if it got a new file spec, 0 if it didn't.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This function is called internally to get the next file spec out of
 | 
						|
//  the input line.  This is simply a matter of parsing past all the 
 | 
						|
//  delimiter characters.  The resulting file spec is stored in
 | 
						|
//  data member mFullWildName.  That member will be the one used to
 | 
						|
//  kick off the next wild card search.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   May 26, 1994  1.0A  : First release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO ALWildCardExpander::GetNextWildName()
 | 
						|
{
 | 
						|
    char wild_spec[ _MAX_PATH ];
 | 
						|
    int i = 0;
 | 
						|
    char *p = mInputLine;
 | 
						|
 | 
						|
    for ( ; ; p++ ) {
 | 
						|
        int c = *p;
 | 
						|
        if ( c != ' ' && c != ',' && c != '\t' )
 | 
						|
            break;
 | 
						|
    }
 | 
						|
    for ( ; ; p++ ) {
 | 
						|
        int c = *p;
 | 
						|
        if ( c == ' ' || c == ',' || c == '\t' || c == '\0' )
 | 
						|
            break;
 | 
						|
        wild_spec[ i++ ] = (char) c;
 | 
						|
        if ( i >= ( _MAX_PATH - 2 ) )
 | 
						|
            return 0;
 | 
						|
    }
 | 
						|
    wild_spec[ i++ ] = '\0';
 | 
						|
    if ( i <= 1 )
 | 
						|
         return 0;
 | 
						|
    mFullWildName = wild_spec;
 | 
						|
    mInputLine = p;
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// char * ALWildCardExpander::GetNextFile()
 | 
						|
//
 | 
						|
// ARGUMENTS:
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  In the event that this routine is able to come up with a new
 | 
						|
//  file name, it returns a character pointer to the name, which
 | 
						|
//  is kept in member variable mResultFileName.  If no new file
 | 
						|
//  name could be cooked up, we return a 0, which means you are
 | 
						|
//  done.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  There are two wild card expander routines.  One for NT, and one
 | 
						|
//  for DOS.  They are both very similar in structure, but they weren't
 | 
						|
//  quite close enough to combine into a single routine.  However, the
 | 
						|
//  both share a common structure, which is being described here.
 | 
						|
//
 | 
						|
//  The ALWildCardExpander has what amounts to six different internal
 | 
						|
//  states.  They are:
 | 
						|
//
 | 
						|
//              Searching subdirectories, using another object
 | 
						|
//
 | 
						|
//              Extracting the next wild spec from the input line
 | 
						|
//
 | 
						|
//              Expanding the wild card to get the first matching file
 | 
						|
//
 | 
						|
//              Expanding the wild card to get the next matching file
 | 
						|
//
 | 
						|
//              Looking for the first subdirectory
 | 
						|
//
 | 
						|
//              Looking for the next subdirectory
 | 
						|
//
 | 
						|
//  For the most part, we keep track of the state using the mState
 | 
						|
//  variable.  However, we keep track of whether we are searching
 | 
						|
//  subdirectories by examining the pointer to the next expander.  If
 | 
						|
//  it is non-null, it means we are in that state.
 | 
						|
//                      
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   May 26, 1994  1.0A  : First release
 | 
						|
//
 | 
						|
 | 
						|
#if defined( AL_WIN32S )
 | 
						|
//
 | 
						|
// This is the NT version.  It has to use FindFirstFile() and
 | 
						|
// FindNextFile() to get file names.  Note that this is implemented
 | 
						|
// as a giant loop.  This means we may go through several states
 | 
						|
// inside this routine until we finally come up with a filename.
 | 
						|
//
 | 
						|
char AL_DLL_FAR * AL_PROTO ALWildCardExpander::GetNextFile()
 | 
						|
{
 | 
						|
    for ( ; ; ) {
 | 
						|
//
 | 
						|
// If the pointer to the next expander is set, it means we are working
 | 
						|
// on a subdirectory, so I have to let him do the work.  If the subdirectory
 | 
						|
// search fails, I continue right back where I was when interrupted.
 | 
						|
//
 | 
						|
        if ( mpNextExpander ) {
 | 
						|
            char *p = mpNextExpander->GetNextFile();
 | 
						|
            if ( p )
 | 
						|
                return p;          // Return the name if he found one
 | 
						|
            delete mpNextExpander; // If not, he is toast
 | 
						|
            mpNextExpander = 0;
 | 
						|
        }
 | 
						|
        switch ( mState ) {
 | 
						|
//
 | 
						|
// This is where I get the next wild spec from the input line.  If
 | 
						|
// there aren't any more, I return 0, because we are done.  If there
 | 
						|
// is one, I set up the member variable that will be used in the
 | 
						|
// rest of the search, and set up the state so that next I will get
 | 
						|
// get the first file name.
 | 
						|
//
 | 
						|
            case GET_NEXT_WILD_NAME :
 | 
						|
                if ( GetNextWildName() == 0 )
 | 
						|
                    return 0;
 | 
						|
                mWildPathOnly = mFullWildName;
 | 
						|
                mWildPathOnly.StripFileName();
 | 
						|
                mWildNameOnly = mFullWildName;
 | 
						|
                mWildNameOnly.StripPath();
 | 
						|
                mState = GET_FIRST_FILE_NAME;
 | 
						|
                break;
 | 
						|
//
 | 
						|
// Once I have a wild spec, time to start getting file names.  
 | 
						|
// FindFirstFile() does it for me.  if there aren't any files, I
 | 
						|
// either go on to search directories, or go the the next wild
 | 
						|
// name in the input line.  If there is a name, I return it to
 | 
						|
// the calling procedure.
 | 
						|
//
 | 
						|
            case GET_FIRST_FILE_NAME :
 | 
						|
                mFindFileHandle = FindFirstFile( mFullWildName, &mFindFileData );
 | 
						|
                if ( mFindFileHandle == INVALID_HANDLE_VALUE ) {
 | 
						|
                    if ( miTraverseFlag )
 | 
						|
                        mState = GET_FIRST_DIRECTORY;
 | 
						|
                    else
 | 
						|
                        mState = GET_NEXT_WILD_NAME;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                mState = GET_NEXT_FILE_NAME;
 | 
						|
                if ( mFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
 | 
						|
                    break;
 | 
						|
                mResultFileName = ALName( mWildPathOnly + mFindFileData.cFileName );
 | 
						|
                return mResultFileName;
 | 
						|
//
 | 
						|
// Time to get another file name with FindNextFile().  If there aren't
 | 
						|
// any more, I clean up, and either get the next name for the input
 | 
						|
// line or start searching subdirectories. If there was a name, I return
 | 
						|
// it to the calling procedure.
 | 
						|
//
 | 
						|
            case GET_NEXT_FILE_NAME :
 | 
						|
                if ( !FindNextFile( mFindFileHandle, &mFindFileData ) ) {
 | 
						|
                    FindClose( mFindFileHandle );
 | 
						|
                    mFindFileHandle = INVALID_HANDLE_VALUE;
 | 
						|
                    if ( miTraverseFlag )
 | 
						|
                        mState = GET_FIRST_DIRECTORY;
 | 
						|
                    else
 | 
						|
                        mState = GET_NEXT_WILD_NAME;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                if ( mFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
 | 
						|
                    break;
 | 
						|
                mResultFileName = ALName( mWildPathOnly + mFindFileData.cFileName );
 | 
						|
                return mResultFileName;
 | 
						|
//
 | 
						|
// The procedure to get the first subdirectory is an awful lot like that
 | 
						|
// we use to get the first file.  If we find a valid subdirectory, we create
 | 
						|
// a new expander to deal with its wildcards.  If we find a file, but
 | 
						|
// it isn't a subdirectory, we keep on searching.  If we don't find
 | 
						|
// anything, we are going to go back and check out the next file spec
 | 
						|
// from the input line.
 | 
						|
// 
 | 
						|
            case GET_FIRST_DIRECTORY :
 | 
						|
                mFindFileHandle = FindFirstFile( mWildPathOnly + "*.*", &mFindFileData );
 | 
						|
                if ( mFindFileHandle == INVALID_HANDLE_VALUE ) {
 | 
						|
                    mState = GET_NEXT_WILD_NAME;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                mState = GET_NEXT_DIRECTORY;
 | 
						|
                if ( mFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
 | 
						|
                    if ( strcmp( mFindFileData.cFileName, ".." ) == 0 )
 | 
						|
                        break;
 | 
						|
                    if ( strcmp( mFindFileData.cFileName, "." ) == 0 )
 | 
						|
                        break;
 | 
						|
                    mpNextExpander = new ALWildCardExpander( mWildPathOnly + mFindFileData.cFileName + "\\" + (char *) mWildNameOnly, 1, mCase );
 | 
						|
                }
 | 
						|
                break;
 | 
						|
//
 | 
						|
// This works the same as the state where I get the first directory.
 | 
						|
// The only difference here is that if I run out of file names in the
 | 
						|
// directory, I have to call FindClose() to clean up after myself.
 | 
						|
//
 | 
						|
            case GET_NEXT_DIRECTORY :
 | 
						|
                if ( !FindNextFile( mFindFileHandle, &mFindFileData ) ) {
 | 
						|
                    FindClose( mFindFileHandle );
 | 
						|
                    mFindFileHandle = INVALID_HANDLE_VALUE;
 | 
						|
                    mState = GET_NEXT_WILD_NAME;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                if ( mFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
 | 
						|
                    if ( strcmp( mFindFileData.cFileName, ".." ) == 0 )
 | 
						|
                        break;
 | 
						|
                    if ( strcmp( mFindFileData.cFileName, "." ) == 0 )
 | 
						|
                        break;
 | 
						|
                    mpNextExpander = new ALWildCardExpander( mWildPathOnly + mFindFileData.cFileName + "\\" + (char *) mWildNameOnly, 1 );
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            default :
 | 
						|
                return 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// This is the MS-DOS version of the file expander.  In structure,
 | 
						|
// it is almost identical to the NT version.
 | 
						|
//
 | 
						|
char AL_DLL_FAR * AL_PROTO ALWildCardExpander::GetNextFile()
 | 
						|
{
 | 
						|
//
 | 
						|
// mpFfblk is the pointer to my structure used by _dos_findfirst()
 | 
						|
// and _dos_findnext().  If for some reason this is a null pointer,
 | 
						|
// I need to quit.  The only reason this should be null is a memory
 | 
						|
// allocation failure.
 | 
						|
//
 | 
						|
    if ( mpFfblk == 0 )
 | 
						|
        return 0;
 | 
						|
    for ( ; ; ) {
 | 
						|
//
 | 
						|
// If the pointer to the next expander is non-zero, it means I am in
 | 
						|
// the middle of a subdirectory search.  If that is the case, I call
 | 
						|
// the next expander to see if it can come up with a file name.  if
 | 
						|
// it does, we return it.  If it doesn't, it means it is done, and
 | 
						|
// I can delete it and try my luck with the next subdirectory.
 | 
						|
//
 | 
						|
        if ( mpNextExpander ) {
 | 
						|
            char *p = mpNextExpander->GetNextFile();
 | 
						|
            if ( p )
 | 
						|
                return p;
 | 
						|
            delete mpNextExpander;
 | 
						|
            mpNextExpander = 0;
 | 
						|
        }
 | 
						|
        switch ( mState ) {
 | 
						|
//
 | 
						|
// This is where I start, and this is where I end up after completely
 | 
						|
// processing one of the input wild specs.  I get the next name from
 | 
						|
// the input line here.  If there aren't any more names, I can return
 | 
						|
// 0, meaning the whole thing is done.
 | 
						|
//
 | 
						|
            case GET_NEXT_WILD_NAME :
 | 
						|
                if ( GetNextWildName() == 0 )
 | 
						|
                    return 0;
 | 
						|
                mWildPathOnly = mFullWildName;
 | 
						|
                mWildPathOnly.StripFileName();
 | 
						|
                mWildNameOnly = mFullWildName;
 | 
						|
                mWildNameOnly.StripPath();
 | 
						|
                mState = GET_FIRST_FILE_NAME;
 | 
						|
                break;
 | 
						|
//
 | 
						|
// Once I have a file name, I start parsing using _dos_findfirst().
 | 
						|
// If that doesn't return a name, I have struck out on my first swing.
 | 
						|
// if that is the case, I either move on to start searching subdirectories,
 | 
						|
// or go back and look for another name from the input line.  On the
 | 
						|
// other hand, if I get a name, I return it to the caller.
 | 
						|
//
 | 
						|
            case GET_FIRST_FILE_NAME :
 | 
						|
                if ( _dos_findfirst( mFullWildName, 0, mpFfblk ) ) {
 | 
						|
                    if ( miTraverseFlag )
 | 
						|
                        mState = GET_FIRST_DIRECTORY;
 | 
						|
                    else
 | 
						|
                        mState = GET_NEXT_WILD_NAME;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                mState = GET_NEXT_FILE_NAME;
 | 
						|
                mResultFileName = ALName( mWildPathOnly + mpFfblk->name );
 | 
						|
                return mResultFileName;
 | 
						|
//
 | 
						|
// This state is identical to GET_FIRST_FILE_NAME, except it has to
 | 
						|
// use _dos_findnext() instead of _dos_findfirst()
 | 
						|
//
 | 
						|
            case GET_NEXT_FILE_NAME :
 | 
						|
                if ( _dos_findnext( mpFfblk ) ) {
 | 
						|
                    if ( miTraverseFlag )
 | 
						|
                        mState = GET_FIRST_DIRECTORY;
 | 
						|
                    else
 | 
						|
                        mState = GET_NEXT_WILD_NAME;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                mResultFileName = mWildPathOnly + mpFfblk->name;
 | 
						|
                return mResultFileName;
 | 
						|
//
 | 
						|
// After getting all of the file names that a wildspec expands into,
 | 
						|
// we can start searching subdirectories, if needed.  Unlike with NT,
 | 
						|
// we can set our search up to look for directories only.  that means
 | 
						|
// we don't have to check the status of the file returned from _dos_findxxxx().
 | 
						|
// However, we always do have to check to make sure it isn't one of the
 | 
						|
// two bogus directory entries, "." or "..".
 | 
						|
//
 | 
						|
// If we score here, we create a new ALWildCardExpander, and put him to
 | 
						|
// work.  If we strike out, time to go back and get our next input
 | 
						|
// file name.
 | 
						|
//
 | 
						|
            case GET_FIRST_DIRECTORY :
 | 
						|
                if ( _dos_findfirst( mWildPathOnly + "*.*", _A_SUBDIR, mpFfblk ) ) {
 | 
						|
                    mState = GET_NEXT_WILD_NAME;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                mState = GET_NEXT_DIRECTORY;
 | 
						|
                if ( mpFfblk->attrib & _A_SUBDIR ) {
 | 
						|
                    if ( strcmp( mpFfblk->name, ".." ) == 0 )
 | 
						|
                        break;
 | 
						|
                    if ( strcmp( mpFfblk->name, "." ) == 0 )
 | 
						|
                        break;
 | 
						|
                    mpNextExpander = new ALWildCardExpander( mWildPathOnly + mpFfblk->name + "\\" + (char *) mWildNameOnly, 1, mCase );
 | 
						|
                }
 | 
						|
                break;
 | 
						|
//
 | 
						|
// This is just like GET_FIRST_DIRECTORY, except it gets to call
 | 
						|
// _dos_findnext() instead of _dos_findfirst().
 | 
						|
//
 | 
						|
            case GET_NEXT_DIRECTORY :
 | 
						|
                if ( _dos_findnext( mpFfblk ) ) {
 | 
						|
                    mState = GET_NEXT_WILD_NAME;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                if ( mpFfblk->attrib & _A_SUBDIR ) {
 | 
						|
                    if ( strcmp( mpFfblk->name, ".." ) == 0 )
 | 
						|
                        break;
 | 
						|
                    if ( strcmp( mpFfblk->name, "." ) == 0 )
 | 
						|
                        break;
 | 
						|
                    mpNextExpander = new ALWildCardExpander( mWildPathOnly + mpFfblk->name + "\\" + (char *) mWildNameOnly, 1 );
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            default :
 | 
						|
                return 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
#if defined( AL_MICROSOFT ) && ( AL_MICROSOFT < 800 )
 | 
						|
    return 0; //MSC 7.0 thinks I need this return path.  No way to get here!
 | 
						|
#endif
 | 
						|
}
 | 
						|
#endif // #if defined( AL_WIN32S )... #else
 |