misc.c

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

C
542
字号
/****************************************************************************
*
*                            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 wmake helper functions.
*
****************************************************************************/


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

#include "make.h"
#include "massert.h"
#include "mmemory.h"
#include "mmisc.h"
#include "mpathgrp.h"
#include "mtypes.h"
#include "mlex.h"

static ENV_TRACKER  *envList;

extern char *SkipWS( char *p )
/*****************************
 * p is not const because the return value is usually used to write data.
 */
{
    while( isws( *p ) ) {
        ++p;
    }
    return( p );
}

extern char *FindNextWS( char *str )
/***********************************
 * Finds next free white space character, allowing doublequotes to
 * be used to specify strings with white spaces.
 *
 * str is not const because the return value is usually used to write data.
 */
{
    char    string_open = 0;

    while( *str != NULLCHAR ) {
        if( *str == BACKSLASH ) {
            str++;
            if( *str != NULLCHAR ) {
                if( !string_open && isws ( *str ) ) {
                    break;
                }
                str++;
            }
        } else {
            if( *str == DOUBLEQUOTE ) {
                string_open = !string_open;
                str++;
            } else {
                if( string_open ) {
                    str++;
                } else {
                    if( isws( *str ) ) {
                        break;
                    }
                    str++;
                }
            }
        }
    }

    return( str );
}

extern char *RemoveDoubleQuotes( char *dst, int maxlen, const char *src )
/************************************************************************
 * Removes doublequote characters from string and copies other content
 * from src to dst. Only maxlen number of characters are copied to dst
 * including terminating NUL character.
 */
{
    char    *orgdst = dst;
    char    string_open = 0;
    int     pos = 0;
    int     t;

    assert( maxlen );

    // leave space for NUL terminator
    maxlen--;

    while( pos < ( maxlen - 1 ) ) {
        t = *src++;

        if( t == NULLCHAR ) {
            break;
        }

        if( t == BACKSLASH ) {
            t = *src++;

            if( t == DOUBLEQUOTE ) {
                *dst++ = DOUBLEQUOTE;
                pos++;
            } else {
                *dst++ = BACKSLASH;
                pos++;

                if( pos < ( maxlen - 1 ) ) {
                    *dst++ = t;
                    pos++;
                }
            }
        } else {
            if( t == DOUBLEQUOTE ) {
                string_open = !string_open;
            } else {
                if( string_open ) {
                    *dst++ = t;
                    pos++;
                } else
                if( isws( t ) ) {
                    break;
                } else {
                    *dst++ = t;
                    pos++;
                }
            }
        }
    }

    *dst = NULLCHAR;

    return( orgdst );
}

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__ ) || defined( __DOS__ )
    return( stricmp( a, b ) );
#else
    return( strcmp( a, b ) );
#endif
}


static int FNameCmpChr( char a, char b )
/**************************************/
{
#if defined( __OS2__ ) || defined( __NT__ ) || defined( __DOS__ )
    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__ ) || defined( __DOS__ )
    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 );
    }
}

/*
 * 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 const char *DoWildCard( const char *base )
/***********************************************/
{
    PGROUP          *pg;
    struct dirent   *entry;

    if( base != NULL ) {
        if( path != NULL ) {        /* clean up from previous invocation */
            FreeSafe( path );
            path = NULL;            /* 1-jun-90 AFS */
        }
        if( pattern != NULL ) {
            FreeSafe( 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 = MallocSafe( _MAX_PATH );
        pattern = MallocSafe( _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 );
        DropPGroup( pg );

        parent = opendir( path );
        if( parent == NULL ) {
            FreeSafe( path );
            path = NULL;
            FreeSafe( 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;
        FreeSafe( path );
        path = NULL;                    /* 1-jun-90 AFS */
        FreeSafe( pattern );
        pattern = NULL;
        return( base );
    }

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

    return( path );
}


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


extern int KWCompare( const char **p1, const char **p2 )    /* for bsearch */
/******************************************************/
{
    return( stricmp( *p1, *p2 ) );
}


extern int PutEnvSafe( ENV_TRACKER *env )
/****************************************
 * This function takes over responsibility for freeing env
 */
{
    char        *p;
    ENV_TRACKER **walk;
    ENV_TRACKER *old;
    int         rc;
    size_t      len;

    p = env->value;
                                // upper case the name
    while( *p != '=' && *p != NULLCHAR ) {
        *p = toupper( *p );
        ++p;
    }
    rc = putenv( env->value );  // put into environment
    if( p[0] == '=' && p[1] == '\0' ) {
        rc = 0;                 // we are deleting the envvar, ignore errors
    }
    len = p - env->value + 1;   // len including '='
    walk = &envList;
    while( *walk != NULL ) {
        if( strncmp( (*walk)->value, env->value, len ) == 0 ) {
            break;
        }
        walk = &(*walk)->next;
    }
    old = *walk;
    if( old != NULL ) {
        *walk = old->next;      // unlink from chain
        FreeSafe( old );
    }
    if( p[1] != 0 ) {           // we're giving it a new value
        env->next = envList;    // save the memory since putenv keeps a
        envList = env;          // pointer to it...
    } else {                    // we're deleting an old value
        FreeSafe( env );
    }
    return( rc );
}


#if !defined(NDEBUG) || defined(DEVELOPMENT)
extern void PutEnvFini( void )
/****************************/
{
    ENV_TRACKER *cur;

    while( envList != NULL ) {
        cur = envList;
        envList = cur->next;
        FreeSafe( cur );
    }
}
#endif

⌨️ 快捷键说明

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