mparse.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,157 行 · 第 1/3 页
C
1,157 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <string.h>
#include "massert.h"
#include "mtypes.h"
#include "mstream.h"
#include "mlex.h"
#include "mtarget.h"
#include "macros.h"
#include "make.h"
#include "mmemory.h"
#include "mparse.h"
#include "mpreproc.h"
#include "mrcmsg.h"
#include "msg.h"
#include "msuffix.h"
#include "mupdate.h"
#include "mvecstr.h"
UINT16 inlineLevel;
STATIC TLIST *firstTarget; /* first set of targets parsed this invocation */
STATIC void ignoring( TOKEN_T t, BOOLEAN freelex )
/*************************************************
* print message saying ignoring token, and if freelex then LexMaybeFree( t )
*/
{
enum MsgClass y;
switch( t ) {
case TOK_SCOLON: y = M_SCOLON; break;
case TOK_DCOLON: y = M_DCOLON; break;
case TOK_FILENAME: y = M_FILENAME; break;
case TOK_DOTNAME: y = M_DOTNAME; break;
case TOK_CMD: y = M_CMD; break;
case TOK_SUF: y = M_SUF; break;
case TOK_SUFSUF: y = M_SUFSUF; break;
case TOK_PATH: y = M_PATH; break;
default:
#ifdef DEVELOPMENT
PrtMsg( FTL | LOC | INVALID_TOKEN_IN, t, "ignoring" );
#else
y = M_UNKNOWN_TOKEN;
#endif
break;
}
PrtMsg( ERR | LOC | IGNORE_OUT_OF_PLACE_M, y );
if( freelex ) {
LexMaybeFree( (TOKEN_T)y );
}
}
STATIC TOKEN_T buildTargs( TLIST **dest, TOKEN_T t )
/***************************************************
* Parse the input, building a TLIST on dest. Accept TOK_FILENAME,
* TOK_SUFSUF and TOK_DOTNAME( if IsDotWithCmds() ). Terminate on
* EOL, STRM_END, TOK_SCOLON, or TOK_DCOLON. Ignore all other tokens.
* returns: token it terminates on
*/
{
char dotname[MAX_DOT_NAME];
assert( dest != NULL );
for( ;; ) { /* read till SCOLON or DCOLON */
switch( t ) {
case TOK_SCOLON: /* fall through */
case TOK_DCOLON:
case EOL:
case STRM_END:
return( t );
case TOK_SUFSUF:
if( !SufBothExist( CurAttr.ptr ) ) {
PrtMsg( ERR | LOC | SUFFIX_DOESNT_EXIST, CurAttr.ptr );
} else {
AddCreator( CurAttr.ptr );
WildTList( dest, CurAttr.ptr, TRUE, TRUE);
}
FreeSafe( CurAttr.ptr );
break;
case TOK_DOTNAME:
if( !IsDotWithCmds( CurAttr.num ) ) {
ignoring( TOK_DOTNAME, TRUE );
} else {
FmtStr( dotname, ".%s", DotNames[CurAttr.num] );
WildTList( dest, dotname, TRUE, TRUE);
}
break;
case TOK_FILENAME:
WildTList( dest, CurAttr.ptr, TRUE, TRUE);
FreeSafe( CurAttr.ptr );
break;
default:
ignoring( t, TRUE );
break;
}
t = LexToken( LEX_PARSER ); /* get next token */
}
}
STATIC void setSColon( const TLIST *tlist, BOOLEAN scolon )
/**********************************************************
* Set the targets in tlist to scolon. Check if any are being
* coerced to double colon, and print an error message.
*/
{
/* set up scolon or dcolon */
for( ; tlist != NULL; tlist = tlist->next ) {
TARGET * const curtarg = tlist->target;
if( !curtarg->special ) {
if( curtarg->depend == NULL ) {
/* initial declaration of target */
curtarg->scolon = scolon;
} else if( scolon != curtarg->scolon ) {
PrtMsg( ERR | LOC | TARGET_ALREADY_M, curtarg->node.name,
curtarg->scolon ? M_SCOLON : M_DCOLON );
}
}
}
}
STATIC void linkDepend( const TLIST *tlist, DEPEND *dep, TATTR attr )
/********************************************************************
* Attach a copy of dep to each target in tlist. Also OR in the attribute
* flags for each target. The pointer to dep is given to the first target.
*/
{
TARGET *curtarg; /* current target we're working on */
DEPEND *targdep; /* last depend for target */
DEPEND **lastnext; /* used to track targdep */
TLIST **endlist; /* used to find last TLIST off a DEPEND */
DEPEND *tmpdep;
for( ; tlist != NULL; tlist = tlist->next ) {
curtarg = tlist->target; /* alias for tlist->target */
if( curtarg->special ) { /* handle special targets */
if( !(curtarg->depend) ) {
// we want to be able to append later to the clist
// if it is a special target
curtarg->depend = NewDepend(); /* no tlist on these */
} else {
/*
* for before and after we need to append command to the end
* if there is a clist. For sufsuf we need to be able to
* add suffixes of different paths so we cannot just destroy
* and create a new Depend
*/
if( !curtarg->before_after && !curtarg->sufsuf ) {
FreeDepend( curtarg->depend );
curtarg->depend = NewDepend();
if( curtarg->dot_default ) {
PrtMsg( WRN | LOC | DOT_DEFAULT_REDEFINITION );
}
}
}
} else {
lastnext = &curtarg->depend;
targdep = *lastnext;
/*
* from here on, *lastnext == targdep; hence, we can modify
* the link to targdep easily.
*/
if( targdep != NULL ) {
/* find last depend in list */
while( targdep->next != NULL ) {
lastnext = &targdep->next;
targdep = targdep->next;
}
if( curtarg->scolon /* && targdep->targs != NULL 14-jul-93 AFS */ ) {
/* We have the case of adding more dependent files to
* a scolon type target. If this happens to be an illegal
* attempt to attach two cmdlists to targ, then it will be
* caught in linkCList().
*/
endlist = &targdep->targs; /* find last dependent */
while( *endlist != NULL ) {
endlist = &(*endlist)->next;
}
tmpdep = dep; /* make a copy of before we hack it up */
dep = DupDepend( tmpdep );
*endlist = tmpdep->targs; /* attach new deps to end */
tmpdep->targs = NULL; /* free useless dep */
FreeDepend( tmpdep );
} else if( targdep->clist != NULL || targdep->targs != NULL ) {
/* target isn't a place holder, link new one in */
targdep->next = dep;
dep = DupDepend( dep );
} else {
/* target is a place holder, free it, and link */
FreeDepend( targdep );
*lastnext = dep;
dep = DupDepend( dep );
}
} else {
*lastnext = dep;
dep = DupDepend( dep );
}
}
TargOrAttr( curtarg, attr );
}
FreeDepend( dep ); /* we'll always make one too many copies */
}
STATIC DEPEND *buildDepend( TATTR *pattr )
/*****************************************
* Parse the next sequence of TOK_FILENAMEs, and .PREC/.SYMB/...
* Build a DEPEND structure containing all the filenames. Set *pattr
* accordingly. Always returns non-null DEPEND *.
*/
{
DEPEND *dep;
TLIST **list;
TOKEN_T t;
dep = NewDepend();
*pattr = FalseAttr;
list = &dep->targs;
for( ;; ) {
t = LexToken( LEX_PARSER );
if( t == EOL || t == STRM_END ) {
break;
}
switch( t ) {
case TOK_DOTNAME:
switch( CurAttr.num ) {
case DOT_ALWAYS:
pattr->always = TRUE;
break;
case DOT_AUTO_DEPEND:
pattr->auto_dep = TRUE;
break;
case DOT_PRECIOUS:
pattr->prec = TRUE;
break;
case DOT_MULTIPLE:
pattr->multi= TRUE;
break;
case DOT_PROCEDURE:
pattr->multi= TRUE;
// fall through
case DOT_SYMBOLIC:
pattr->symb = TRUE;
break;
case DOT_EXPLICIT:
pattr->explicit = TRUE;
break;
case DOT_EXISTSONLY:
pattr->existsonly = TRUE;
break;
case DOT_RECHECK:
pattr->recheck = TRUE;
break;
default:
ignoring( TOK_DOTNAME, TRUE );
break;
}
break;
case TOK_FILENAME:
WildTList( list, CurAttr.ptr, TRUE, FALSE );
FreeSafe( CurAttr.ptr ); /* not needed any more */
while( *list != NULL ) { /* find tail again */
list = &(*list)->next;
}
break;
default:
ignoring( t, TRUE );
break;
}
}
return( dep );
}
STATIC void checkFirstTarget( void )
/**********************************/
{
TLIST *head;
TLIST *current;
TLIST *okayList; /* List containing the still valid initial targets */
TLIST *notOkayList; /* Tlist of targets not valid anymore */
TLIST *temp;
okayList = NULL;
notOkayList = NULL;
head = firstTarget;
if( head != NULL ) {
/* Go through all the targets to see check if still OK */
current = head;
while( current != NULL ) {
if( !current->target->attr.explicit &&
!current->target->special ) {
/* still valid targets */
temp = okayList;
okayList = current;
current = current->next;
okayList->next = temp;
} else {
/* probably a '::' rule that changed to .explicit */
temp = notOkayList;
notOkayList = current;
current = current->next;
notOkayList->next = temp;
}
}
FreeTList( notOkayList );
head = NULL;
/* Reverse the list back */
while( okayList != NULL ) {
temp = head;
head = okayList;
okayList = okayList->next;
head->next = temp;
}
firstTarget = head;
}
}
STATIC void setFirstTarget( const TLIST *tlist )
/**********************************************/
{
/* Check to see if first targets are still valid */
checkFirstTarget();
if( firstTarget == NULL ) {
firstTarget = DupTList( tlist );
/* Check to see if any of the new targets are valid */
checkFirstTarget();
}
}
STATIC void parseTargWarning( const TLIST *walk )
/************************************************
* we check if any targets are not special, and print a warning if so
*/
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?