misc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 401 行

C
401
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Miscellaneous, wildcard functions.
*
****************************************************************************/


#if defined( __UNIX__ )
  #include <dirent.h>
#else
  #include <direct.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <ctype.h>
#include <assert.h>
#include "misc.h"

#define NULLCHAR '\0'

#define WILD_METAS "*?"

#ifdef __UNIX__
  #define IGNORE_MASK        ( 0 )
#else
  #define IGNORE_MASK        ( _A_VOLID )
#endif

typedef struct PathGroup {
    char    *drive;
    char    *dir;
    char    *fname;
    char    *ext;
    char    buffer[PATH_MAX + 4];
} PGROUP;

extern char *FixName( char *name )
{
#if defined( __DOS__ )
/*********************************
 * Down case all filenames, converting fwd-slash to back-slash
 */
    char    *ptr;
    char    hold;

    assert( name != NULL );

    ptr = name;
    hold = *ptr;
    for( ;; ) {
        if( hold == NULLCHAR ) {
            break;
        }
        if( hold == '/' ) {
            *ptr = '\\';
        } else if( ( hold -= 'A' ) < 26 ) {     /* SIDE EFFECT!!! */
            *ptr = hold + 'a';
        }
        hold = *++ptr;
        if( hold == NULLCHAR ) {
            break;
        }
        if( hold == '/' ) {
            *ptr = '\\';
        } else if( ( hold -= 'A' ) < 26 ) {     /* SIDE EFFECT!!! */
            *ptr = hold + 'a';
        }
        hold = *++ptr;
    }

    return( name );
#elif defined( __OS2__ ) || defined( __NT__ )
/*********************************
 * convert fwd-slash to back-slash
 */
    char    *ptr;
    char    hold;

    assert( name != NULL );

    ptr = name;
    hold = *ptr;
    for( ;; ) {
        if( hold == NULLCHAR ) {
            break;
        }
        if( hold == '/' ) {
            *ptr = '\\';
        }
        hold = *++ptr;
        if( hold == NULLCHAR ) {
            break;
        }
        if( hold == '/' ) {
            *ptr = '\\';
        }
        hold = *++ptr;
    }

    return( name );
#else
    return( name );
#endif
}


extern int FNameCmp( const char *a, const char *b )
/*************************************************/
{
#if defined( __OS2__ ) || defined( __NT__ )
    return( stricmp( a, b ) );
#else
    return( strcmp( a, b ) );
#endif
}


static int FNameCmpChr( char a, char b )
/**************************************/
{
#if defined( __OS2__ ) || defined( __NT__ )
    return( tolower( a ) - tolower( b ) );
#else
    return( a - b );
#endif
}


#ifdef USE_FAR
extern int _fFNameCmp( const char FAR *a, const char FAR *b )
/***********************************************************/
{
#if defined( __OS2__ ) || defined( __NT__ )
    return( _fstricmp( a, b ) );
#else
    return( _fstrcmp( a, b ) );
#endif
}
#endif


#define IS_WILDCARD_CHAR( x ) ((*x == '*') || (*x == '?'))

static int __fnmatch( char *pattern, char *string )
/**************************************************
 * OS specific compare function FNameCmpChr
 * must be used for file names
 */
{
    char    *p;
    int     len;
    int     star_char;
    int     i;

    /*
     * check pattern section with wildcard characters
     */
    star_char = 0;
    while( IS_WILDCARD_CHAR( pattern ) ) {
        if( *pattern == '?' ) {
            if( *string == 0 ) {
                return( 0 );
            }
            string++;
        } else {
            star_char = 1;
        }
        pattern++;
    }
    if( *pattern == 0 ) {
        if( (*string == 0) || star_char ) {
            return( 1 );
        } else {
            return( 0 );
        }
    }
    /*
     * check pattern section with exact match
     * ( all characters except wildcards )
     */
    p = pattern;
    len = 0;
    do {
        if( star_char ) {
            if( string[len] == 0 ) {
                return( 0 );
            }
            len++;
        } else {
            if( FNameCmpChr( *pattern, *string ) != 0 ) {
                return( 0 );
            }
            string++;
        }
        pattern++;
    } while( *pattern && !IS_WILDCARD_CHAR( pattern ) );
    if( star_char == 0 ) {
        /*
         * match is OK, try next pattern section
         */
        return( __fnmatch( pattern, string ) );
    } else {
        /*
         * star pattern section, try locate exact match
         */
        while( *string ) {
            if( FNameCmpChr( *p, *string ) == 0 ) {
                for( i = 1; i < len; i++ ) {
                    if( FNameCmpChr( *(p + i), *(string + i) ) != 0 ) {
                        break;
                    }
                }
                if( i == len ) {
                    /*
                     * if rest doesn't match, find next occurence
                     */
                    if( __fnmatch( pattern, string + len ) ) {
                        return( 1 );
                    }
                }
            }
            string++;
        }
        return( 0 );
    }
}

extern PGROUP *SplitPath( const char *path )
/******************************************/
{
    PGROUP      *pg;
    size_t      len;

    assert( path != NULL );

    pg = malloc( sizeof( PGROUP ) );
    _splitpath2( path, pg->buffer, &pg->drive, &pg->dir, &pg->fname, &pg->ext );
    /*
     *  I don't really want to make the assumption that _splitpath2 will
     *  fill in the buffer like so:
     *
     *      drive \0 dir \0 fname \0 ext \0
     *
     *  but it would be incredibly slow to assume otherwise.
     *
     */
    len = ( pg->ext + strlen( pg->ext ) + 1 ) - pg->buffer;
    len += sizeof( PGROUP ) - _MAX_PATH2;
    realloc( pg, len );
    return( pg );
}

/*
 * THIS FUNCTION IS NOT RE-ENTRANT!
 *
 * It returns a pointer to a character string, after doing wildcard
 * substitutions.  It returns NULL when there are no more substitutions
 * possible.
 *
 * DoWildCard behaves similarly to strtok.  You first pass it a pointer
 * to a substitution string.  It checks if the string contains wildcards,
 * and if not it simply returns this string.  If the string contains
 * wildcards, it attempts an opendir with the string.  If that fails it
 * returns the string.
 *
 * If the opendir succeeds, or you pass DoWildCard a NULL pointer, it reads
 * the next normal file from the directory, and returns the filename.
 *
 * If there are no more files in the directory, or no directory is open,
 * DoWildCard returns null.
 *
 */

static DIR  *parent = NULL;  /* we need this across invocations */
static char *path = NULL;
static char *pattern = NULL;

extern char *DoWildCard( char *base )
/***********************************************/
{
    PGROUP          *pg;
    struct dirent   *entry;

    if( base != NULL ) {
        if( path != NULL ) {        /* clean up from previous invocation */
            free( path );
            path = NULL;            /* 1-jun-90 AFS */
        }
        if( pattern != NULL ) {
            free( pattern );
            pattern = NULL;
        }
        if( parent != NULL ) {
            closedir( parent );
            parent = NULL;          /* 1-jun-90 AFS */
        }

        if( strpbrk( base, WILD_METAS ) == NULL ) {
            return( base );
        }
        // create directory name and pattern
        path = malloc( _MAX_PATH );
        pattern = malloc( _MAX_PATH );
        strcpy( path, base );
        FixName( path );
        pg = SplitPath( path );
        _makepath( path, pg->drive, pg->dir, ".", NULL );
        // create file name pattern
        _makepath( pattern, NULL, NULL, pg->fname, pg->ext );
        free( pg );

        parent = opendir( path );
        if( parent == NULL ) {
            free( path );
            path = NULL;
            free( pattern );
            pattern = NULL;
            return( base );
        }
    }

    if( parent == NULL ) {
        return( NULL );
    }

    assert( path != NULL && parent != NULL );

    entry = readdir( parent );
    while( entry != NULL ) {
#ifndef __UNIX__
        if( ( entry->d_attr & IGNORE_MASK ) == 0 ) {
#endif
            if( __fnmatch( pattern, entry->d_name ) ) {
                break;
            }
#ifndef __UNIX__
        }
#endif
        entry = readdir( parent );
    }
    if( entry == NULL ) {
        closedir( parent );
        parent = NULL;
        free( path );
        path = NULL;                    /* 1-jun-90 AFS */
        free( pattern );
        pattern = NULL;
        return( base );
    }

    pg = SplitPath( path );
    _makepath( path, pg->drive, pg->dir, entry->d_name, NULL );
    free( pg );

    return( path );
}


extern void DoWildCardClose( void )
/*********************************/
{
    if( path != NULL ) {
        free( path );
        path = NULL;
    }
    if( pattern != NULL ) {
        free( pattern );
        pattern = NULL;
    }
    if( parent != NULL ) {
        closedir( parent );
        parent = NULL;
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?