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
 |