mupdate.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,176 行 · 第 1/3 页

C
1,176
字号
/****************************************************************************
*
*                            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:  Target update processing.
*
****************************************************************************/


#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <utime.h>

#include "make.h"
#include "macros.h"
#include "massert.h"
#include "mcache.h"
#include "mmemory.h"
#include "mexec.h"
#include "mmisc.h"
#include "mlex.h"
#include "mpathgrp.h"
#include "mpreproc.h"
#include "mrcmsg.h"
#include "msg.h"
#include "msuffix.h"
#include "mtarget.h"
#include "mtypes.h"
#include "mupdate.h"
#include "mvecstr.h"
#include "mautodep.h"


STATIC BOOLEAN checkForAutoDeps( TARGET *targ, char *name, time_t *max_time );

/*
 *  exStack is used to stack the special macro pointers during ExecCList()
 *  calls.
 */
struct exStack {
    TARGET  *targ;
    DEPEND  *dep;
    DEPEND  *impDep;
};

#define MAX_EXSTACK 16
STATIC struct exStack   exStack[MAX_EXSTACK];
STATIC UINT8            exStackP;
STATIC BOOLEAN          doneBefore;     /* executed the .BEFORE commands? */
STATIC UINT32           cListCount;     /* number of CLISTs executed so far */

BOOLEAN DoingUpdate;

const char *MonthNames[] = {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

#define USE_AUTO_DEP( x )   ((Glob.auto_depends != 0) || ((x)->attr.auto_dep != 0))

extern void exPush( TARGET *targ, DEPEND *dep, DEPEND *impDep )
/*************************************************************/
{
    if( exStackP == MAX_EXSTACK ) {
        PrtMsg( FTL| PERCENT_MAKE_DEPTH );
    }
    exStack[exStackP].targ   = targ;
    exStack[exStackP].dep    = dep;
    exStack[exStackP].impDep = impDep;
    ++exStackP;
}


extern void exPop( void )
/***********************/
{
    assert( exStackP > 0 );
    --exStackP;
}


STATIC signed int dateCmp( time_t targ, time_t dep )
/**************************************************/
{
    if( (targ < dep) || Glob.all ) {
        return( -1 );
    } else if( targ > dep ) {
        return( 1 );
    } else {
        return( 0 );
    }
}


STATIC void getStats( TARGET *targ )
/**********************************/
{
    if( targ->executed ) {
        targ->executed = FALSE;
        if( targ->touched ) {           /* used with symbolic, -t, -n, -q */
            targ->date = YOUNGEST_DATE;
            targ->existing = TRUE;
        } else if( targ->attr.symb ) {
            targ->existing = FALSE;
            targ->date = OLDEST_DATE;
        } else if( CacheTime( targ->node.name, &targ->date ) != RET_SUCCESS ) {
            /* if file doesn't exist make it old */
            targ->date = OLDEST_DATE;
            targ->existing = FALSE;
            /* useful in those rare cases when a file has been deleted */
        } else {
            targ->existing = TRUE;
        }
    } /* else: no changes in the status */
}


#ifdef __WATCOMC__
#pragma on (check_stack);
#endif
STATIC BOOLEAN targExists( TARGET *targ )
/***************************************/
{
    char    buffer[_MAX_PATH];

    getStats( targ );           /* get date stamp */
    if( targ->existing ) {
        return( TRUE );
    }
    if( targ->attr.symb ) {
        return( FALSE );
    }

    if( TrySufPath( buffer, targ->node.name, NULL, FALSE ) == RET_SUCCESS ) {
        RenameTarget( targ, buffer );
        targ->executed = TRUE;              /* force get date */
        getStats( targ );
        assert( targ->existing );
        return( TRUE );
    }
    return( FALSE );
}
#ifdef __WATCOMC__
#pragma off(check_stack);
#endif


STATIC void getDate( TARGET *targ )
/*********************************/
{
    getStats( targ );
    if( Glob.debug ) {
        char        buf[20];    /* large enough for date */
        struct tm   *tm;

        if( targ->date == YOUNGEST_DATE ) {
            FmtStr( buf, "%M", M_YOUNGEST_DATE );
        } else if( targ->date == OLDEST_DATE ) {
            FmtStr( buf, "%M", M_OLDEST_DATE );
        } else {
            tm = localtime( &targ->date );
            FmtStr( buf, "%D-%s-%D  %D:%D:%D",
                    tm->tm_mday, MonthNames[tm->tm_mon], tm->tm_year,
                    tm->tm_hour, tm->tm_min, tm->tm_sec
                );
        }
        PrtMsg( DBG | INF | GETDATE_MSG, buf, targ->node.name );
    }
}


#ifdef __WATCOMC__
#pragma on (check_stack);
#endif
STATIC RET_T carryOut( TARGET *targ, CLIST *clist, time_t max_time )
/******************************************************************/
{
    CLIST               *err;
    int                 i;
    struct utimbuf      times;
    char                msg[max( MAX_RESOURCE_SIZE, _MAX_PATH )];

    assert( targ != NULL && clist != NULL );

    ++cListCount;
    if( ExecCList( clist ) == RET_SUCCESS ) {
        if( Glob.rcs_make && !Glob.noexec && !Glob.touch ) {
            if( max_time != OLDEST_DATE ) {
                targ->date = max_time;
                targ->backdated = TRUE;
                if( TrySufPath( msg, targ->node.name, NULL, FALSE ) == RET_SUCCESS ) {
                    if( USE_AUTO_DEP( targ ) ) {
                        // target has auto dependency info
                        // result: max_time may be incorrect!
                        CacheRelease();
                        checkForAutoDeps( targ, msg, &max_time );
                    }
                    times.actime = max_time;
                    times.modtime = max_time;
                    utime( msg, &times );
                    CacheRelease();
                }
            }
        }
        targ->cmds_done = TRUE;
        return( RET_SUCCESS );
    }

    /*
     * ok - here is something I don't like.  In this portion of code here,
     * carryOut is ignoring the target passed to it, and digging the targets
     * out of the stack.  Be careful of changes.
     */
    PrtMsg( ERR | NEOL | LAST_CMD_MAKING_RET_BAD );
    for( i = exStackP - 1; i >= 0; --i ) {
        PrtMsg( ERR | NEOL | PRNTSTR, exStack[i].targ->node.name );
        if( i > 0 ) {
            PrtMsg( ERR | NEOL | PRNTSTR, ";" );
        }
    }
    MsgGetTail( LAST_CMD_MAKING_RET_BAD, msg );
    PrtMsg( ERR | PRNTSTR, msg );

    err = DotCList( DOT_ERROR );
    if( err != NULL ) {
        ++cListCount;
        if( ExecCList( err ) != RET_SUCCESS ) {
            PrtMsg( FTL | S_COMMAND_RET_BAD, DotNames[DOT_ERROR] );
        }
    } else if( !(targ->attr.prec || targ->attr.symb) ) {
        if( !Glob.hold && targExists( targ ) ) {
            if( Glob.erase || GetYes( SHOULD_FILE_BE_DELETED ) ) {
                if( unlink( targ->node.name ) != 0 ) {
                    PrtMsg( FTL | SYSERR_DELETING_FILE, targ->node.name );
                }
            }
        }
    }
    if( Glob.cont ) {
        return( RET_WARN );
    }
    exit( ExitSafe( EXIT_ERROR ) );
    return( RET_ERROR );
}
#ifdef __WATCOMC__
#pragma off(check_stack);
#endif


STATIC time_t maxDepTime( time_t max_time, DEPEND *dep )
/******************************************************/
{
    TLIST   *targets;

    for( targets = dep->targs; targets != NULL; targets = targets->next ) {
        if( targets->target->date <= max_time )
            continue;
        if( targets->target->date == YOUNGEST_DATE )
            continue;
        max_time = targets->target->date;
    }
    return( max_time );
}


STATIC time_t findMaxTime( TARGET *targ, DEPEND *imp_dep, time_t max_time )
/*************************************************************************/
{
    DEPEND  *dep;

    max_time = maxDepTime( max_time, imp_dep );
    for( dep = targ->depend; dep != NULL; dep = dep->next ) {
        max_time = maxDepTime( max_time, dep );
    }
    return( max_time );
}


STATIC RET_T perform( TARGET *targ, DEPEND *dep, time_t max_time )
/****************************************************************/
{
    CLIST   *clist;
    CLIST   *before;
    RET_T   ret;
    DEPEND  *depend;
    DEPEND  *impliedDepend;

    depend = NULL;
    impliedDepend = NULL;
    assert( targ != NULL && dep != NULL );

    if( Glob.query ) {
        ++cListCount;
        return( RET_WARN );
    }
    if( Glob.touch ) {
        ++cListCount;
        ResetExecuted();
        if( targ->attr.symb == FALSE ) {
            CacheRelease();
            if( TouchFile( targ->node.name ) != RET_SUCCESS ) {
                PrtMsg( ERR | COULD_NOT_TOUCH, targ->node.name );
                return( RET_ERROR );
            }
        }
        targ->touched = TRUE;
        return( RET_SUCCESS );
    }

    /* means that this is a sufsuf made implicit rule */
    if( dep->slistCmd == NULL ) {
        clist = dep->clist;
        depend = dep;
        impliedDepend = NULL;
    } else {
        clist = DupCList( dep->slistCmd->clist );
        depend = targ->depend;
        impliedDepend = dep;
    }
    if( clist == NULL ) {
        clist = DotCList( DOT_DEFAULT );
        if( clist == NULL ) {
            // No commands in Microsoft and POSIX mode is considered OK
            // and executed
            if( Glob.microsoft || Glob.posix ) {
                targ->cmds_done = TRUE;
                return( RET_SUCCESS );
            }
            if( targ->attr.symb != FALSE ) {    /* 13-Dec-90 DJG */
                targ->cmds_done = TRUE;
                return( RET_SUCCESS );
            }
            if( targ->allow_nocmd ) {
                /* for UNIX folks: make target symbolic */
                targ->attr.symb = TRUE;
                return( RET_SUCCESS );
            }
            PrtMsg( FTL | NO_DEF_CMDS_FOR_MAKE,
                DotNames[DOT_DEFAULT], targ->node.name );
        }
    }
    if( !Glob.noexec ) {
        ResetExecuted();
    }
    if( !doneBefore ) {
        before = DotCList( DOT_BEFORE );
        if( before != NULL ) {
            ++cListCount;
            if( ExecCList( before ) != RET_SUCCESS ) {
                PrtMsg( FTL | S_COMMAND_RET_BAD, DotNames[DOT_BEFORE] );
            }
        }
        doneBefore = TRUE;
    }
    exPush( targ, depend, impliedDepend );
    ret = carryOut( targ, clist, findMaxTime( targ, dep, max_time ) );
    exPop();
    if( dep->slistCmd != NULL ) {
        FreeCList(clist);
    }
    return( ret );
}


extern RET_T MakeList( TLIST *tlist )
/***********************************/
{
    RET_T   ret;

⌨️ 快捷键说明

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