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, × );
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 + -
显示快捷键?