⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stmt.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 4 页
字号:
/* 
Copyright 1994-2003 Free Software Foundation, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  

This program is derived from the cc68k complier by 
Matthew Brandt (mattb@walkingdog.net) 

You may contact the author of this derivative at:

mailto::camille@bluegrass.net

or by snail mail at:

David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
 */
/*
 * Statement parser
 */
#include <stdio.h> 
#include <string.h>
#include <ctype.h>
#include "lists.h"
#include "expr.h" 
#include "c.h" 
#include "ccerr.h"
#include "diag.h"
 
extern int prm_oldfor;
extern TYP stdint;
extern int funcnesting;
extern int prm_c99;
extern int defaulttype;
extern int indefaultinit;
extern int stdpragmas;
extern int block_nesting;
extern char *cpp_funcname_tab[];
extern LIST *instantiated_inlines;
extern LIST *local_using_list,  *local_tag_using_list;
extern SYM undef;
extern ENODE *block_rundown;
extern int lastch;
extern enum e_sym lastst, lastlastst;
extern char lastid[];
extern TABLE lsyms, oldlsym, ltags, oldltag;
extern int lineno;
extern SYM *currentfunc;
extern int skm_closepa[];
extern int incldepth;
extern short unalteredline[4096];
extern int prm_cplusplus, prm_debug;
extern int prm_ansi;
extern int vtabhead;
extern int currentfile;
extern FILELIST *lastinc;
extern int dbgblocknum;
extern short *lptr;
extern int prm_cmangle;
extern int arg_nesting;
extern SNODE *funcendstmt;
extern SYM *typequal;
extern char declid[];
extern SYM *catch_cleanup_func,  *global_vararray_func;
extern TYP **headptr,  *head;
extern int prm_xcept;
extern int skm_declend[];
extern int global_flag;
extern int stdaddrsize, stdintsize;
extern ENODE *expr_runup[];
extern ENODE *expr_rundown[];
extern int expr_updowncount;
extern int infuncargs;
extern int gotoCount;

int selectscalar(TYP *tp)
{
    return tp->type == bt_pointer && !tp->val_flag || scalarnoncomplex(tp) ;
}
int incatchclause;
int asmline;
int skm_openpa[] = 
{
    openpa, begin, semicolon, 0
};
int skm_semi[] = 
{
    semicolon, end, 0
};
int skm_tocase[] = 
{
    kw_case, kw_default, end, 0
};
long nextlabel, firstlabel;
int goodcode;

TRYBLOCK *try_block_list;

#define CASE_MAX 512
struct caselist {
    struct caselist *next;
    int last;
    LLONG_TYPE cases[CASE_MAX];
} *currentCases ;

static int gotellipse;
static char phibuf[4096];
static int lastlineno = 0;
static int switchbreak;
static int hasdefault;
static int inswitch;
static int switchwidth;

SNODE *cbautoinithead,  *cbautoinittail,  *cbautorundownhead, 
    *cbautorundowntail;
LASTDEST *lastDestPointer;


void stmtini(void)
{
    lastlineno = 0;
    nextlabel = firstlabel = 1;
    goodcode = 0;
    asmline = FALSE;
    lastDestPointer = 0;
    inswitch = 0;
}
/* get the size of the expression, and cast up to int as necessary */
static TYP *stmtsize(ENODE **node, TYP *tp)
{
#ifdef XXXXX
    TYP *rv;
    enum e_bt t1 ;
    if (!tp || !*node)
        return tp;
    t1 = tp->type;
    if (t1 <= bt_int)
        t1 = bt_int;
    else if (t1 <= bt_unsigned)
        t1 = bt_unsigned;
    
    rv = inttype(t1);
    if (rv->type != tp->type)
        promote_type(rv,node);
    return rv ;
#else
    return tp;
#endif
}
/* scan an expression and determine if there are any pias */
TYP *doassign(ENODE **exp, int canerror, int *skm)
{
    TYP *tp;
    goodcode |= GF_INIF;
    if ((tp = expression(exp, TRUE)) == 0)
    {
        if (canerror)
            generror(ERR_EXPREXPECT, 0, skm);
        *exp = makenode(en_nacon, &undef, 0);
    }
    goodcode &= ~GF_INIF;
    // cast to higher level
    tp = stmtsize(exp,tp);
    return tp;
}

//-------------------------------------------------------------------------

SNODE *whilestmt(void)
/* 
 *      whilestmt parses the c while statement. 
 */
{
    SNODE *snp;
    int ogc = goodcode;
    TYP *tp ;
    goodcode |= GF_INLOOP;
    snp = xalloc(sizeof(SNODE));
    snp->next = 0;
    snp->stype = st_while;
    snp->s1 = 0;
    getsym();
    needpunc(openpa, 0);
    tp = doassign(&snp->exp, TRUE, 0);
    if (tp)
    {
        if (tp->type == bt_cond)
            tp = tp->btp ;
        if (!selectscalar(tp)) 
            generror(ERR_SELECTSCALAR, 0, 0);
    }
    needpunc(closepa, skm_closepa);
    goodcode |= GF_CONTINUABLE | GF_BREAKABLE;
    snp->s1 = cppblockedstatement(TRUE);
    goodcode = ogc;
    return snp;
}

//-------------------------------------------------------------------------

SNODE *dostmt(void)
/* 
 *      dostmt parses the c do-while construct. 
 */
{
    SNODE *snp;
    TYP *tp;
    int ogc = goodcode, oswb = switchbreak;
    goodcode |= GF_INLOOP;
    snp = xalloc(sizeof(SNODE));
    snp->next = 0;
    snp->stype = st_do;
    getsym();
    goodcode |= GF_CONTINUABLE | GF_BREAKABLE;
    snp->s1 = cppblockedstatement(TRUE);
    goodcode = ogc;
    if (lastst != kw_while)
        gensymerror(ERR_IDENTEXPECT, lastid);
    else
        getsym();
    needpunc(openpa, 0);
    tp = doassign(&snp->exp, TRUE, 0);
    if (tp)
    {
        if (tp->type == bt_cond)
            tp = tp->btp ;
        if (!selectscalar(tp)) 
            generror(ERR_SELECTSCALAR, 0, 0);
    }

    needpunc(closepa, skm_closepa);
    if (lastst != eof)
        needpunc(semicolon, 0);
    switchbreak = oswb;
    return snp;
}

//-------------------------------------------------------------------------

SNODE *forstmt(void)
/*
 * Generate a block for a for statement
 */
{
    SNODE *snp,  *forexp;
    int ogc = goodcode, oswb = switchbreak;
    int plussemi = 0;
    int declared = 0;
    int oldpragma;
    TABLE ools, oolt;
    goodcode |= GF_INLOOP;
    snp = xalloc(sizeof(SNODE));
    snp->next = 0;
    getsym();
    snp->label = snp->exp = snp->s2 = 0;
    snp->stype = st_for;
    if (needpunc(openpa, skm_closepa))
    {
            /* CPLUSPLUS allows you to declare a variable here */
            if (castbegin(lastst) || lastst == kw_auto || lastst == kw_register)
            {
                if (prm_cplusplus || prm_c99)
                {
                    ENODE *exp = 0,  **next = &exp;
                    cbautoinithead = cbautoinittail = 0;
                    ools = oldlsym;
                    oldlsym = lsyms;
                    oolt = oldltag;
                    oldltag = ltags;
                    oldpragma = stdpragmas;
                    declared = 1;
                    blockdecl();
                    while (cbautoinithead)
                    {
                        if (*next)
                        {
                            *next = makenode(en_void, (*next), cbautoinithead
                                ->exp);
                            next = &(*next)->v.p[1];
                        }
                        else
                             *next = cbautoinithead->exp;
                        cbautoinithead = cbautoinithead->next;
                    }
                    snp->label = exp;
                    plussemi = 1;
                }
                else
                {
                    generror(ERR_NODECLARE, 0, 0);
                    snp->label = makenode(en_nacon, &undef, 0);
                    while (castbegin(lastst))
                        getsym();
                    goto forjoin;
                }
            }
            else
            forjoin: 
        {
            if (expression(&snp->label, TRUE) == 0)
                snp->label = 0;
            plussemi = needpunc(semicolon, 0);
        }
        if (plussemi)
        {
            TYP *tp;
            goodcode |= GF_INIF;
            tp = expression(&snp->exp, TRUE);
            tp = stmtsize(&snp->exp, tp);
            if (tp)
            {
                if (tp->type == bt_cond)
                    tp = tp->btp ;
                if (!selectscalar(tp)) 
                    generror(ERR_SELECTSCALAR, 0, 0);
            }
            forexp = snp->exp;
            goodcode &= ~GF_INIF;
            //                  doassign(&snp->exp,FALSE,0);
            if (needpunc(semicolon, 0))
            {
                if (expression(&snp->s2, TRUE) == 0)
                {
                    snp->s2 = 0;
                }
            }
        }
        needpunc(closepa, skm_closepa);
    }
    goodcode |= GF_CONTINUABLE | GF_BREAKABLE;
    snp->s1 = cppblockedstatement(TRUE);
    if (declared && !prm_oldfor)
    {
        SYM *q = lsyms.head;
        gather_labels(&oldlsym, &lsyms);
        while (q && q->next != oldlsym.head)
            q = q->next;
        if (q)
            q->next = 0;
        addblocklist(lsyms.head, oldlsym.head);
        addrundown(snp);
        check_funcused(&oldlsym, &lsyms);
        if (oldlsym.head != lsyms.head)
            arg_nesting++;
        stdpragmas = oldpragma;
        lsyms = oldlsym;
        oldlsym.head = ools.head;
        ltags = oldltag;
        oldltag.head = oolt.head;
    }
    goodcode = ogc;
    if (!switchbreak && !forexp)
        goodcode |= GF_UNREACH;
    switchbreak = oswb;
    return snp;
}

//-------------------------------------------------------------------------

SNODE *ifstmt(void)
/* 
 *      ifstmt parses the c if statement and an else clause if 
 *      one is present. 
 */
{
    SNODE *snp;
    int ogc = goodcode;
    int temp = 0, temp1 = 0;
    TYP *tp;
    snp = xalloc(sizeof(SNODE));
    snp->next = 0;
    snp->stype = st_if;
    getsym();
    needpunc(openpa, 0);
    tp = doassign(&snp->exp, TRUE, 0);
    if (tp)
    {
        if (tp->type == bt_cond)
            tp = tp->btp ;
        if (!selectscalar(tp)) 
            generror(ERR_SELECTSCALAR, 0, 0);
    }
    
    needpunc(closepa, skm_closepa);
    snp->s1 = cppblockedstatement(FALSE);
    temp1 = goodcode &(GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO | GF_THROW);
    if (lastst == kw_else)
    {
        temp = goodcode &(GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO |
            GF_THROW);
        goodcode = ogc;
        getsym();
        snp->s2 = cppblockedstatement(FALSE);
        temp = temp &goodcode;
    }
    else
        snp->s2 = 0;
    goodcode = ogc | (temp &temp1);
    return snp;
}

//-------------------------------------------------------------------------

SNODE *casestmt(void)
/* 
 *      cases are returned as seperate statements. for normal 
 *      cases label is the case value and s2 is zero. for the 
 *      default case s2 is nonzero. 
 */
{
    SNODE *snp;
    SNODE *head = 0,  *tail;
    LLONG_TYPE ssize;
    snp = xalloc(sizeof(SNODE));
    snp->next = 0;
    if (lastst == kw_case)
    {
        struct caselist *cc = currentCases;
        getsym();
        snp->s2 = 0;
        snp->stype = st_case;
        snp->switchid = (ssize = intexpr(0));
        snp->label = (SNODE *)-1;
        if (switchwidth == 1 && (ssize &0xffffff00) || switchwidth == 2 && (ssize &0xffff0000)
            || switchwidth ==  - 1 && (ssize <  - 0x80 || ssize > 0x7f) || switchwidth ==  -
            2 && (ssize <  - 0x8000 || ssize > 0x7fff))
            generror(ERR_LOSTCONVCASE, 0, 0);
        while (cc) {
            int i;
            for (i=0; i < cc->last; i++)
                if (ssize == cc->cases[i]) {
                    generror(ERR_DUPCASE,ssize,0);
                    cc = 0;
                    break ;
                }
            if (cc && !cc->next) {

⌨️ 快捷键说明

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