csloops.c

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

C
372
字号
/****************************************************************************
*
*                            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:  processing for all looping structures
*
****************************************************************************/


#include "ftnstd.h"
#include "errcod.h"
#include "opr.h"
#include "opn.h"
#include "global.h"
#include "stmtsw.h"
#include "fmemmgr.h"
#include "recog.h"
#include "ferror.h"
#include "insert.h"
#include "utility.h"

extern  void            CkTypeDeclared(void);
extern  void            AddCSNode(byte);
extern  void            DelCSNode(void);
extern  void            BlockLabel(void);
extern  void            ColonLabel(void);
extern  void            CSNoMore(void);
extern  void            CSExtn(void);
extern  void            Match(void);
extern  void            CSCond(label_id);
extern  void            GLabel(label_id);
extern  void            GBranch(label_id);
extern  label_id        NextLabel(void);
extern  unsigned_32     LkUpDoTerm(void);
extern  sym_id          STShadow(sym_id);
extern  void            STUnShadow(sym_id);
extern  void            Recurse(void);
extern  void            GDoInit(TYPE);
extern  void            GDoEnd(void);
extern  void            FreeLabel(label_id);
extern  void            RemKeyword(itnode *,int);
extern  void            BIOutSymbol(sym_id);


static  void    InitLoop( int loop_type ) {
//=========================================

    AddCSNode( loop_type );
    CSHead->branch = NextLabel();
    CSHead->bottom = NextLabel();
    CSHead->cycle = NextLabel();
    GLabel( CSHead->branch );
}


static  void    FiniLoop(void) {
//==========================

    GBranch( CSHead->branch );
    GLabel( CSHead->bottom );
    FreeLabel( CSHead->branch );
    FreeLabel( CSHead->bottom );
    FreeLabel( CSHead->cycle );
}


void    CpLoop(void) {
//================

// Compile a LOOP statement.

    CSExtn();
    InitLoop( CS_LOOP );
    BlockLabel();
}


void    CpEndLoop(void) {
//===================

// Compile an ENDLOOP statment.

    if( CSHead->typ == CS_LOOP ) {
        GLabel( CSHead->cycle );
        FiniLoop();
    } else {
        Match();
    }
    DelCSNode();
    CSNoMore();
}


void    CpWhile(void) {
//=================

// Compile a WHILE statement.
//    WHILE( expr )DO <:label> -- block while
//    WHILE( expr )   <:label> -- block while
//    WHILE( expr ) STATEMENT  -- one line while

    CSExtn();
    InitLoop( CS_WHILE );
    CSCond( CSHead->bottom );
    if( RecNOpn() && RecNextOpr( OPR_COL ) ) {
        BlockLabel();
    } else if( RecKeyWord( "DO" ) &&
               ( RecNextOpr( OPR_TRM ) || RecNextOpr( OPR_COL ) ) ) {
        CITNode->opn.ds = DSOPN_PHI;
        BlockLabel();
    } else {
        Recurse();
        GLabel( CSHead->cycle );
        FiniLoop();
        DelCSNode();
    }
}


void    CpEndWhile(void) {
//====================

// Compile an ENDWHILE statement.

    if( CSHead->typ == CS_WHILE ) {
        GLabel( CSHead->cycle );
        FiniLoop();
    } else {
        Match();
    }
    DelCSNode();
    CSNoMore();
}


void    CpUntil(void) {
//=================

// Compile an UNTIL statement.

    if( ( CSHead->typ == CS_LOOP ) || ( CSHead->typ == CS_WHILE ) ) {
        GLabel( CSHead->cycle );
        CSCond( CSHead->branch );
        GLabel( CSHead->bottom );
        FreeLabel( CSHead->branch );
        FreeLabel( CSHead->bottom );
        FreeLabel( CSHead->cycle );
    } else {
        Match();
    }
    DelCSNode();
    CSNoMore();
}


static  unsigned_32     DoLabel(void) {
//=================================

    unsigned_32 term;

    if( RecNumber() ) {
        term = LkUpDoTerm();
        AdvanceITPtr();
        if( !RecNOpr() && !RecComma() ) {
            Error( DO_NO_COMMA_OR_VAR );
        }
    } else {
        term = 0;
    }
    return( term );
}


void    CpDo(void) {
//==============

// Compile a DO statement.

    signed_32   term;

    AddCSNode( CS_DO );
    term = DoLabel();
    if( term == 0 ) {
        Extension( DO_DO_EXT );
    }
    InitDo( term );
    ColonLabel();
}


void    CpDoWhile(void) {
//===================

// Compile a DO WHILE statement.

    Extension( DO_DO_EXT );
    InitLoop( CS_DO_WHILE );
    CSHead->cs_info.do_term = DoLabel();
    if( RecKeyWord( "WHILE" ) ) {
        RemKeyword( CITNode, 5 );
        CSCond( CSHead->bottom );
        BlockLabel();
    } else {
        if( ReqNOpn() ) {
            BlockLabel();
        }
    }
}


void    CpEndDo(void) {
//=================

// Compile an ENDDO statement.

    if( CSHead->typ == CS_DO ) {
        if( CSHead->cs_info.do_parms->do_term == 0 ) {
            TermDo();
        } else {
            BadDoEnd();
        }
    } else if( CSHead->typ == CS_DO_WHILE ) {
        if( CSHead->cs_info.do_term == 0 ) {
            TermDoWhile();
        } else {
            BadDoEnd();
        }
    } else {
        Match();
    }
    CSNoMore();
}


static  void    BadDoEnd(void) {
//==========================

    Error( DO_BAD_ENDDO );
    FreeLabel( CSHead->branch );
    FreeLabel( CSHead->bottom );
    DelCSNode();
}


void    InitDo( signed_32 term ) {
//================================

// Initialize a DO or implied DO.
// Process "do i=e1,e2,e3" where e1, e2 and e3 are numeric expressions.
//

    do_entry    *do_pointer;
    sym_id      do_var;

    if( ( StmtSw & SS_DATA_INIT ) == 0 ) {
        CSHead->branch = NextLabel();
        CSHead->bottom = NextLabel();
        CSHead->cycle = NextLabel();
    }
    do_pointer = FMemAlloc( sizeof( do_entry ) );
    CSHead->cs_info.do_parms = do_pointer;
    do_pointer->do_term = term;
    do_pointer->do_parm = NULL;
    if( ReqDoVar() ) {
        CkTypeDeclared();
        do_var = CITNode->sym_ptr;
        BIOutSymbol( do_var );
        do_var->ns.flags |= SY_REFERENCED;
        do_var->ns.xflags |= SY_DEFINED;
        if( do_var->ns.flags & SY_DO_PARM ) {
            Error( DO_PARM_REDEFINED );
        }
        do_pointer->do_parm = do_var;   // remember id of "i"
        ReqNextOpr( OPR_EQU, EQ_NO_EQUALS );
        if( StmtSw & SS_DATA_INIT ) {
            if( !_IsTypeInteger( do_var->ns.typ ) ) {
                NameErr( DA_BAD_DO_VAR, do_var );
            }
            do_var = STShadow( do_var );
            CITNode->flags = do_var->ns.flags;
        }
        CITNode->sym_ptr = do_var;
        GDoInit( do_var->ns.typ );
        do_var->ns.flags |= SY_DO_PARM;
    }
}


void    ImpDo(void) {
//===============

    AddCSNode( CS_DO );
    InitDo( 0 );
}


void    TermDo(void) {
//================

// Terminate a DO or an implied DO.

    do_entry    *do_pointer;
    sym_id      do_var;

    if( CSHead->typ == CS_DO ) {
        do_pointer = CSHead->cs_info.do_parms;
        if( do_pointer->do_parm != NULL ) {
            if( ( StmtSw & SS_DATA_INIT ) == 0 ) {
                GLabel( CSHead->cycle );
            }
            GDoEnd();
            do_var = do_pointer->do_parm;
            if( (do_var->ns.flags & SY_SPECIAL_PARM) &&
                !(do_var->ns.flags & SY_PS_ENTRY) ) {
                STUnShadow( do_var );
            }
            do_var->ns.flags &= ~SY_DO_PARM;
            if( ( StmtSw & SS_DATA_INIT ) == 0 ) {
                GLabel( CSHead->bottom );
            }
        }
    } else {
        Match();
    }
    if( ( StmtSw & SS_DATA_INIT ) == 0 ) {
        FreeLabel( CSHead->branch );
        FreeLabel( CSHead->bottom );
        FreeLabel( CSHead->cycle );
    }
    DelCSNode();
}


void            TermDoWhile(void) {
//=============================

    GLabel( CSHead->cycle );
    FiniLoop();
    DelCSNode();
}


void    CpContinue(void) {
//====================

// Compile a CONTINUE statement.

    CSNoMore();
}

⌨️ 快捷键说明

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