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

📄 stmt.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * C compiler * ========== * * Copyright 1989, 1990, 1991 Christoph van Wuellen. * Credits to Matthew Brandt. * All commercial rights reserved. * * This compiler may be redistributed as long there is no * commercial interest. The compiler must not be redistributed * without its full sources. This notice must stay intact. * * History: * * 1989   starting an 68000 C compiler, starting with material *        originally by M. Brandt * 1990   68000 C compiler further bug fixes *        started i386 port (December) * 1991   i386 port finished (January) *        further corrections in the front end and in the 68000 *        code generator. *        The next port will be a SPARC port *//****************************************************************************** * *  The statement module handles all of the possible c statements and builds a *  parse tree of the statements. * *  Each routine returns a pointer to a statement parse node which reflects the *  statement just parsed. * *****************************************************************************/#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"/********************************************************** Static Variables */#ifndef SYNTAX_CORRECTstatic BOOL return_found = FALSE;	/* return statement encountered */static int break_lvl = 0;	/* nesting depth of break statements */static int cont_lvl = 0;	/* nesting depth of continue statements */static int case_lvl = 0;	/* nesting depth of case statements */static BOOL need_label = FALSE;#endif /* SYNTAX_CORRECT *//*********************************************** Static Function Definitions */static STMT *mk_stmt P_ ((STMTTYPE));static STMT *whilestmt P_ ((void));static STMT *dostmt P_ ((void));static STMT *forstmt P_ ((void));static STMT *ifstmt P_ ((void));static STMT *casestmt P_ ((void));static STMT *switchstmt P_ ((void));static STMT *retstmt P_ ((void));static STMT *breakstmt P_ ((void));static STMT *contstmt P_ ((void));static STMT *exprstmt P_ ((void));static STMT *labelstmt P_ ((void));static STMT *gotostmt P_ ((void));static STMT *statement P_ ((void));static STMT *compound P_ ((void));#ifdef TRACEstatic STMT *tracestmt P_ ((void));#endif /* TRACE *//*****************************************************************************/

/*
 *   walkstmt() descends the statement tree recursively.
 */
#if defined(__STDC__) || defined(__cplusplus)
STMT * walkstmt (STMT *stmts, STMT *(*stmtfunc) (STMT *),
		      EXPR *(*exprfunc) (EXPR *))
#else
STMT * walkstmt (stmts, stmtfunc, exprfunc)
     STMT   *stmts;
     STMT   *(*stmtfunc) ();
     EXPR   *(*exprfunc) ();

#endif
{
    STMT    *stmt;

    for (stmt = (*stmtfunc) (stmts); stmt != NIL_STMT; stmt = stmt->next) {
	switch (stmt->stype) {
	case st_return:
	case st_expr:
	    stmt->exp = (*exprfunc) (stmt->exp);
	    break;
	case st_while:
	case st_do:
	    stmt->exp = (*exprfunc) (stmt->exp);
	    stmt->s1 = walkstmt (stmt->s1, stmtfunc, exprfunc);
	    break;
	case st_for:
	    stmt->exp = (*exprfunc) (stmt->exp);
	    stmt->v1.e = (*exprfunc) (stmt->v1.e);
	    stmt->s1 = walkstmt (stmt->s1, stmtfunc, exprfunc);
	    stmt->v2.e = (*exprfunc) (stmt->v2.e);
	    break;
	case st_if:
	    stmt->exp = (*exprfunc) (stmt->exp);
	    stmt->s1 = walkstmt (stmt->s1, stmtfunc, exprfunc);
	    stmt->v1.s = walkstmt (stmt->v1.s, stmtfunc, exprfunc);
	    break;
	case st_switch:
	    stmt->exp = (*exprfunc) (stmt->exp);
	    stmt->v1.s = walkstmt (stmt->v1.s, stmtfunc, exprfunc);
	    break;
	case st_case:
	case st_default:
	case st_label:
	    stmt->v1.s = walkstmt (stmt->v1.s, stmtfunc, exprfunc);
	    break;
	case st_compound:
	    stmt->s1 = walkstmt (stmt->s1, stmtfunc, exprfunc);
	    break;
	case st_goto:
	case st_break:
	case st_continue:
#ifdef ASM
	case st_asm:
#endif /* ASM */
	    break;
	default:
	    CANNOT_REACH_HERE ();
	    break;
	}
	stmt->next = (*stmtfunc) (stmt->next);
    }
    return stmts;
}

/*****************************************************************************/static STMT *mk_stmt P1 (STMTTYPE, st){    STMT   *snp;    snp = (STMT *) xalloc (sizeof (STMT));    snp->stype = st;    snp->next = NIL_STMT;    snp->exp = NIL_EXPR;    snp->s1 = NIL_STMT;#ifdef DEBUGOPT    snp->line = act_line;    snp->linetxt = mk_string (act_linetxt);#endif /*DEBUGOPT */    return snp;}
#ifdef DOINLINE
static STMT *copystmt P1 (const STMT *, stmt)
{
    STMT *snp;

    if (stmt == NIL_STMT)
	return NIL_STMT;

    snp = mk_stmt (stmt->stype);
    switch (stmt->stype) {
    case st_return:
    case st_expr:
	snp->exp = stmt->exp;
	break;
    case st_while:
    case st_do:
	snp->exp = stmt->exp;
	snp->s1 = stmt->s1;
	break;
    case st_for:
	snp->exp = stmt->exp;
	snp->v1.e = stmt->v1.e;
	snp->s1 = stmt->s1;
	snp->v2.e = stmt->v2.e;
	break;
    case st_if:
	snp->exp = stmt->exp;
	snp->s1 = stmt->s1;
	snp->v1.s = stmt->v1.s;
	break;
    case st_switch:
	snp->exp = stmt->exp;
	snp->v1.s = stmt->v1.s;
	break;
    case st_case:
    case st_default:
    case st_label:
	snp->v1.s = stmt->v1.s;
	break;
    case st_compound:
	snp->s1 = stmt->s1;
	break;
    case st_goto:
    case st_break:
    case st_continue:
#ifdef ASM
    case st_asm:
#endif /* ASM */
	break;
    default:
	CANNOT_REACH_HERE ();
	break;
    }
    snp->next = stmt->next;

    return snp;
}

static STMT * copystmttree P1 (STMT *, stmt)
{
    STMT *snp;
    int save_global_flag = global_flag;

    global_flag++;
    snp = walkstmt (stmt, copystmt, copynode);
    global_flag = save_global_flag;

    return snp;
}
#endif /* DOINLINE */
#ifndef SYNTAX_CORRECT/* * returns TRUE if the stmt is a "NULL" statement */static BOOL is_empty_statement P1 (const STMT *, snp){    if (snp == NIL_STMT)	return TRUE;    switch (snp->stype) {    case st_compound:	return is_empty_statement (snp->s1);    default:	return FALSE;    }}/* * check to see if the expression is a constant expression ... used * to see if conditional expressions are "invariant". */static void check_unconditional P2 (const EXPR *, ep, const char *, str){    if (ep != NIL_EXPR) {	if (tst_const (ep)) {	    message (WARN_CONST, str);	} else if ((ep->nodetype == en_test) &&		   (ep->v.p[0]->nodetype == en_sym) &&		   is_array_type (ep->v.p[0]->etp)) {	    message (WARN_ARRAY, str);	}    }}#endif /* SYNTAX_CORRECT *//* * whilestmt parses the c while statement. */static STMT *whilestmt P0 (void){    STMT   *snp;#ifndef SYNTAX_CORRECT    break_lvl++;    cont_lvl++;#endif /* SYNTAX_CORRECT */    snp = mk_stmt (st_while);    getsym ();    needpunc (tk_openpa);    snp->exp = condition_expression ();    needpunc (tk_closepa);    snp->s1 = statement ();#ifndef SYNTAX_CORRECT    need_label = FALSE;    break_lvl--;    cont_lvl--;#endif /* SYNTAX_CORRECT */    return snp;}/* * dostmt parses the c do-while construct. */static STMT *dostmt P0 (void){    STMT   *snp;#ifndef SYNTAX_CORRECT    break_lvl++;    cont_lvl++;#endif /* SYNTAX_CORRECT */    snp = mk_stmt (st_do);    getsym ();    snp->s1 = statement ();    needpunc (kw_while);    needpunc (tk_openpa);    snp->exp = condition_expression ();    needpunc (tk_closepa);    needpunc (tk_semicolon);#ifndef SYNTAX_CORRECT    need_label = FALSE;    break_lvl--;    cont_lvl--;#endif /* SYNTAX_CORRECT */    return snp;}static STMT *forstmt P0 (void){    STMT   *snp;#ifndef SYNTAX_CORRECT    break_lvl++;    cont_lvl++;#endif /* SYNTAX_CORRECT */    snp = mk_stmt (st_for);    getsym ();    needpunc (tk_openpa);    if (lang_option >= LANG_C99 && is_declaration_specifier (lastst)) {	lc_auto = declaration_list (sc_auto, lc_auto);    } else {	snp->exp = expression ();#ifndef SYNTAX_CORRECT	sequence_point ();	check_discard (snp->exp);#endif /* SYNTAX_CORRECT */	needpunc (tk_semicolon);    }    if (lastst != tk_semicolon) {	snp->v1.e = condition_expression ();    } else {	snp->v1.e = NIL_EXPR;    }    needpunc (tk_semicolon);    snp->v2.e = expression ();#ifndef SYNTAX_CORRECT    sequence_point ();    check_discard (snp->v2.e);#endif /* SYNTAX_CORRECT */    needpunc (tk_closepa);    snp->s1 = statement ();#ifndef SYNTAX_CORRECT    need_label = FALSE;    break_lvl--;    cont_lvl--;#endif /* SYNTAX_CORRECT */    return snp;}/* * ifstmt parses the c if statement and an else clause if one is present. */static STMT *ifstmt P0 (void){    STMT   *snp;    snp = mk_stmt (st_if);    getsym ();    if (lastst == tk_openpa) {#ifndef SYNTAX_CORRECT	BOOL    needlab;#endif /* SYNTAX_CORRECT */	getsym ();	snp->exp = condition_expression ();#ifndef SYNTAX_CORRECT	check_unconditional (snp->exp, "if");#endif /* SYNTAX_CORRECT */	needpunc (tk_closepa);	snp->s1 = statement ();#ifndef SYNTAX_CORRECT	needlab = need_label;	need_label = FALSE;#endif /* SYNTAX_CORRECT */	if (lastst == kw_else) {	    getsym ();	    snp->v1.s = statement ();	} else {	    snp->v1.s = NIL_STMT;#ifndef SYNTAX_CORRECT	    /* check for a dangling else statement ... bad coding style? */	    if ((snp->s1 != NIL_STMT) && (snp->s1->stype == st_if) &&		(snp->s1->v1.s != NIL_STMT)) {		message (WARN_ELSE);	    }#endif /* SYNTAX_CORRECT */	}#ifndef SYNTAX_CORRECT	need_label = need_label && needlab;	if (is_empty_statement (snp->s1) && is_empty_statement (snp->v1.s)) {	    message (WARN_EMPTYIF);	}    } else {	message (ERR_EXPREXPECT);#endif /* SYNTAX_CORRECT */    }    return snp;}/* * consider the following piece of code: * *      switch (i) { *              case 1: *                      if (j) { *                              ..... *                      } else *              case 2: *                      .... *      } * * case statements may be deep inside, so we need a global variable * last_case to link them */static STMT *last_case;		/* last case statement within this switch */static TYP *last_switch_type;	/* type of switch controlling expression *//* * cases are returned as separate statements. for normal cases label is the * case value and v1.i is zero. for the default case v1.i is nonzero. */static STMT *casestmt P0 (void){    STMT   *snp;    BOOL   ignore = FALSE;    if (lastst == kw_case) {	getsym ();	snp = mk_stmt (st_case);	snp->v2.i = intexpr ();	/*	 * The constant expression in each case label is converted to the	 * promoted type of the controlling expression.	 */	if (last_switch_type) {	    if (!is_representable (snp->v2.i, last_switch_type)) {		message (WARN_REPRESENT, (long) snp->v2.i,			  nameoftype (last_switch_type));
		ignore = TRUE;	    }	}    } else {	/* lastst is kw_default */	getsym ();	snp = mk_stmt (st_default);    }    snp->s1 = NIL_STMT;    if (!ignore) {	if (last_case) {	    last_case->s1 = snp;	}	last_case = snp;    }    needpunc (tk_colon);    snp->v1.s = statement ();#ifndef SYNTAX_CORRECT    if (case_lvl == 0) {	message (ERR_CASE);	snp = snp->v1.s;    }#endif /* SYNTAX_CORRECT */    return snp;}#ifndef SYNTAX_CORRECT/* * check_cases will check to see if any duplicate cases exist in the case list * pointed to by casehead. */static void check_cases P1 (const STMT *, casehead){    const STMT *top, *cur;    for (top = casehead; top != NIL_STMT; top = top->s1) {	for (cur = top->s1; cur != NIL_STMT; cur = cur->s1) {	    if (cur->stype == st_default) {		if (top->stype == st_default) {		    message (ERR_DUPDEFAULT);		    return;		}	    } else {		if (top->stype != st_default && cur->v2.i == top->v2.i) {		    message (ERR_DUPCASE, cur->v2.i);		    return;		}	    }

⌨️ 快捷键说明

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