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 + -
显示快捷键?