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

📄 ccstmt.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
**
**	<postfix-expr> ::= <postfix-expr> '++'	(postincrement operator)
**			| <postfix-expr> '--'	(postdecrement operator)
**			| <primary-expr>
**
**	<sizeof-expr> ::= 'sizeof' '(' <type-name> ')'
**			| 'sizeof' <prefix-expr>	(*)
**						
**	(*) = the reason this is <prefix-expr> instead of <unary-expr> is
** to reflect the fact that a cast expression cannot be used there since
** it would be interpreted as the other kind of sizeof expression.
**
** Notes on unary expr ops:
**				Operand	Convs	Result	Lvalue result
**	Cast			any	any	any	no
**	Sizeof			any	-	int	no
**	Unary minus: -()	arith	unary	=	no
**	Logical negate: !()	scalar	unary	int(0/1) no
**	Bitwise negate: ~()	integ	unary	=	no
**	Address: &()		lvalue	-	*()	no
**	Indirect: *()		ptr	unary	obj	yes
**	Prefix inc/dec:	++ --	scalar	bin	=	no
**	Postfix inc/dec: ++ --	scalar	bin	=	no
*/

static NODE *
castexpr()
{
    NODE *n;
    TYPE *t;

    if (token != T_LPAREN)
	return unary();
    nextoken();			/* Peek at next token */
    if (csymbol && (tok[token].tktype == TKTY_RWTYPE
			|| csymbol->Sclass == SC_TYPEDEF))
	{
	t = typename();		/* Parse the type-name */
	expect(T_RPAREN);
	n = convcast(t, convarrfn(castexpr()));
					/* Get expression, apply cast */
	n->Nflag |= NF_USERCAST;	/* Say this was explicit user cast */
	return n;
	}
    tokpush(T_LPAREN, (SYMBOL *)NULL);	/* Not a cast, push token back */
    return unary();			/* and parse unary-expr instead! */
}

static NODE *
unary()
{
    NODE *n;
    int op;

    switch (token)
	{
	default:
	    return postexpr();	/* Parse <postfix-expr> */
	case T_SIZEOF:
	    return sizeexpr();	/* Parse <sizeof-expr> */

	case T_INC:
	    nextoken();		/* ++() Prefix increment */
	    return pincdec(unary(), N_PREINC);
	case T_DEC:
	    nextoken();		/* --() Prefix decrement */
	    return pincdec(unary(), N_PREDEC);

	case Q_COMPL:
	    op = Q_COMPL;
	    break;	/* ~()  Bitwise not */
	case Q_NOT:
	    op = Q_NOT;
	    break;	/* !()  Logical not */
	case Q_PLUS:
	    op = Q_PLUS;
	    break;	/* +() Unary plus */
	case Q_MINUS:
	    op = N_NEG;
	    break;	/* -() Arithmetic negation */
    
	    /* KAR-11/91, changed value of ra_expr for this case  */
            /* to 20 if ra_expr is 0 and 21 if ra_expr is 1       */
	case Q_ANDT:
	    op = N_ADDR;		/* &() Address of */
	    if (ra_expr)
		ra_expr = 21;
	    else
		ra_expr = 20;
	    break;

	case Q_MPLY:
	    op = N_PTR;
	    break;	/* *() Indirection */
	}
    nextoken();			/* Have a prefix op, move on to next token */
    n = castexpr();		/* and parse cast-expr following the op */
    if (n->Ntype->Tspec == TS_VOID)
	error("Unary operand cannot have void type");

    switch (op)
	{
	case N_PREINC:		/* ++() Prefix increment */
	case N_PREDEC:		/* --() Prefix decrement */
	    n = pincdec(n, op);
	    break;

	case Q_COMPL:		/* ~()  Bitwise not */
	    if (!tisinteg(n->Ntype))	/* Check for integral type */
		{
		error("Operand of ~ must have integral type");
		return ndeficonst(0);
		}
	    n = convunary(n);			/* Convert if needed */
	    return ndef(op, n->Ntype, 0, n, (NODE*)NULL);	/* Result has converted type */

	case Q_NOT:			/* !()  Logical not */
	    n = convunary(n);		/* Apply conversions */
	    if (!tisscalar(n->Ntype))	/* Check for scalar type */
		{
		error("Operand of ! must have scalar type");
		return ndeficonst(0);
		}
					/* Note result type is always int! */
	    return ndef(op, inttype, 0, n, (NODE*)NULL);

	case Q_PLUS:		/* +() Unary plus */
	    if (!tisarith(n->Ntype))	/* Check for arithmetic type */
		{
		error("Operand of + must have arithmetic type");
		return ndeficonst(0);
		}
	    return convunary(n);		/* Apply integral promotions */

	case N_NEG:			/* -() Arithmetic negation */
	    if (!tisarith(n->Ntype))	/* Check for arithmetic type */
		{
		error("Operand of - must have arithmetic type");
		return ndeficonst(0);
		}
				/* Apply the usual unary conversions */
	    n = convunary(n);			/* Convert if needed */
	    return ndef(op, n->Ntype, 0, n, (NODE*)NULL);	/* Result has cvted type */


	case N_ADDR:		/* &() Address of */
	/* No unary conversions apply here.  Only check for lvalue.
	** Application to functions and arrays is tricky.
	**	Level	&(fun of T)		&(array of T)
	**	-----	-----------		-------------
	**	base:	error			error
	**	carm:	warn (ptr to fun of T)	warn (ptr to T)
	**	ansi:	OK   (ptr to fun of T)	OK   (ptr to array of T)
	*/

	    if (n->Ntype->Tspec == TS_FUNCT || n->Ntype->Tspec == TS_ARRAY)
		{
		switch (clevel)
		    {
		    default:
		    case CLEV_BASE:
			error("& applied to array or function");
			return convarrfn(n);
		    case CLEV_CARM:
		    case CLEV_ANSI:
			warn("& applied to array or function");
			return convarrfn(n);	/* Let this convert to addr */
		    case CLEV_STDC:
			if (n->Ntype->Tspec == TS_FUNCT)
			    return convarrfn(n);
			break;			/* For array, drop thru. */
		    }
		}
	    if (!(n->Nflag & NF_LVALUE))	/* Operand must be lvalue */
		error("Operand of & must be lvalue");
	    if (n->Nop == Q_IDENT)
		if (n->Nid->Sclass == SC_RAUTO || n->Nid->Sclass == SC_RARG)
#if 0
		    if (clevel < CLEV_STRICT)
			warn("& applied to register variable: non-portable!");
		    else
#endif
			error("& applied to register variable");

	    if (tisbitf(n->Ntype))
#if 0
		if (clevel < CLEV_STRICT)
		    warn("& applied to bitfield: non-portable!");
		else
#endif
		    error("& applied to bitfield");

	    n = ndef(N_ADDR, n->Ntype, 0, n, (NODE*)NULL);
	    if (!(n->Nleft->Nflag & NF_GLOBAL)) /* If object has local extent */
		{
		stackrefs++;		/* then count it as a */
		n->Nflag |= NF_STKREF;	/* stack reference */
		}
	    n->Ntype = findtype(TS_PTR, n->Ntype); /* add ref to type */
	    break;

	case N_PTR:			/* *() Indirection */
	    return ptrapply(n);	/* Use common routine */
	default:
	    ;	/* do nothing */
	}
    return n;
}

/* PTRAPPLY - Apply "*" operator to an expression.
**	This is a common subroutine rather than part of unary() because
** array subscripting wants to invoke "*" as well.
*/
static NODE *
ptrapply(n)
NODE *n;
{
    n = convunary(n);			/* Apply usual unary conversions */
    if (n->Ntype->Tspec != TS_PTR)
	{
	error("Operand of * must have pointer type");
	n->Ntype = findtype(TS_PTR, n->Ntype);	/* patch up */
	}
    if (n->Ntype->Tsubt->Tspec == TS_VOID)
	{
	error("Operand of * cannot be ptr to void");
	return ndeficonst(0);
	}
    n = ndef(N_PTR, n->Ntype->Tsubt, 0, n, (NODE*)NULL);

    if (debcsi == KCC_DBG_NULL)
	{
	n->sfline = fline;
	n->Nflag |= NF_USENPD;
	}

    if (n->Nleft->Nflag & NF_STKREF)	/* If addr was on stack, */
	stackrefs--;			/* "*" cancels existence of addr. */
    else
	n->Nflag |= NF_GLOBAL;		/* Not stack addr so must be global */

    if (n->Ntype->Tspec != TS_FUNCT)
	n->Nflag |= NF_LVALUE;		/* Result is lvalue unless function */
    return n;
}

/* SIZEEXPR - Handle "sizeof" operator.
**	Note that the size is always in terms of TGSIZ_CHAR size bytes,
** rather than the actual # bits used by a "char" type; the latter can vary
** (mainly if -x=ch7 was specified), but by fiat we always measure objects
** in terms of 9-bit bytes so that everything will divide evenly and not
** confuse library routines and so forth.
**	The exception is arrays; char arrays always return the number of
** elements (chars) in the array, regardless of the size of a char.
** Similarly, the size of a char is always 1, regardless of the actual # of
** bits it uses.
*/
static NODE *
sizeexpr(void)
{
    TYPE *t;
    NODE *n, *e;
    int saveconst = constexpr;		/* save state of constexpr flag */

    /*
     * Suspend restrictions on parsing of constant expressions 
     */

    constexpr = 0;

    n = ndeft(N_ICONST, siztype);	/* Get node for integer constant */
					/* Use special type for "sizeof" */
    t = NULL;
    if (nextoken() == T_LPAREN)	/* Check for possible type-name */
	{
	nextoken();
	if(csymbol && (tok[token].tktype == TKTY_RWTYPE
		|| csymbol->Sclass == SC_TYPEDEF))
	    {
	    t = typename();
	    expect(T_RPAREN);
	    }
	else	/* Not a reserved-word type or typedef, push paren back. */
	    tokpush(T_LPAREN, (SYMBOL *)NULL);
	}

    if (t == NULL)	/* If no type-name seen, get a prefix-expression. */
	{
	e = unary();		/* Get expr, without fun/arr convs */
	t = e->Ntype;		/* and use type of the expression */

	/* Special check for string constant, which normally doesn't
	** have the size set in its type.
	*/
	if (e->Nop == N_SCONST)	/* Is it string constant? */
	    {
	    n->Niconst = e->Nsclen;	/* Yes, return length! */
	    constexpr = saveconst;	/* restore state of flag */
	    return n;
	    }
	}

    /* Have type, now determine its size */
    n->Niconst = 0;			/* Clear in case of error */
    switch (t->Tspec)
	{
	case TS_VOID:
	    warn("Operand of sizeof has void type");
	    break;

	case TS_FUNCT:
	    error("Operand of sizeof has function type");
	    break;

	case TS_ARRAY:
	    if (t->Tsize == 0)
		{
		error("Size of array not known");
		n->Niconst = 0;
		break;
		}
	    if (tischararray(t))		/* If char array, */
		{
		n->Niconst = sizearray(t);	/* size is # of elements */
		break;
		}
		/* 8/91 ensure short s[1] is size 2 NOT 4 (SPR 9578) */
	    if (t->Tsubt->Tspec == TS_SHORT ||
		    t->Tsubt->Tspec == TS_USHORT)
		{
		n->Niconst = sizearray(t)*2;
		break;
		}
		/* Drop through */
	case TS_STRUCT:
	case TS_UNION:	/* (size in wds)*(chars per word) */
	    n->Niconst = sizetype(t) * (TGSIZ_WORD/TGSIZ_CHAR);
	    break;

	case TS_CHAR:
	case TS_UCHAR:
	    n->Niconst = 1; /* char always takes one byte */
	    break;

	case TS_BITF:
	case TS_UBITF:
	    error("Operand of sizeof has bitfield type");
		/* Drop through */

		/* Anything left had better be a scalar type! */
	default:
	    if (!tisscalar(t))
		int_error("sizeexpr: invalid type: %d", t->Tspec);
	    n->Niconst = (tbitsize(t) + TGSIZ_CHAR-1) / TGSIZ_CHAR;
	    break;
	}
    constexpr = saveconst;	/* restore state of constexpr flag */
    return n;			/* return the filled in const node */
}


/* POSTEXPR - Parse postfix expression
**	[dpANS 3.3.2]
**
**	<postfix-expr> ::= <primary-expr>
**		| <postfix-expr> '[' <expr> ']'		Array subscript
**		| <postfix-expr> '(' {arg-expr-list} ')'	Function call
**		| <postfix-expr> '.' <ident>		Direct component sel
**		| <postfix-expr> "->" <ident>		Indirect component sel
**		| <postfix-expr> "++"			Post-increment
**		| <postfix-expr> "--"			Post-decrement
**
** Current token is 1st token of a postfix expression.
** On return, current token is the next one after the expression.
*/

static NODE *
postexpr()
{
    int op;
    INT off;
    NODE *n;
    TYPE *tp, *mt;
    SYMBOL *sy;

    n = primary();		/* First get primary expression */
    for (;;)
	switch (token)	/* Loop to handle all postfixes */
	    {
	    case T_LPAREN:
	    /* Parse function call ::=	<postfix-expr> '(' {arg-expr-list} ')'
	    ** [dpANS 3.3.2.2]
	    */
		tp = n->Ntype;		/* Remember function type */
		sy = n->Nop == Q_IDENT ? n->Nid : NULL;	/* Get ident if one */
		switch (tp->Tspec)
		    {
		    case TS_FUNCT:
			break;	/* Should be this */
		    case TS_PTR:		/* OK to be this */
			sy = NULL;
			if (tp->Tsubt->Tspec == TS_FUNCT)
			    {
			    if (clevel < CLEV_ANSI)
				warn("Assuming ptr to function is function");
			    tp = tp->Tsubt;
			    if (n->Nop == N_ADDR)	/* Simplify &f() to f() */
				{
				n = n->Nleft;
				sy = n->Nop == Q_IDENT ? n->Nid : NULL;
				}
			    else			/* Use addr */
				{
				n = ndef(N_PTR, tp, 0, n, (NODE*)NULL);

				if (debcsi == KCC_DBG_NULL)
				    {
				    n->sfline = fline;
				    n->Nflag |= NF_USENPD;
				    }
				}
			    break;
			    }
		    /* Else fall thru to fail */
		    default:
			error("Call to non-function");
			n = ndeft(N_UNDEF, tp = findftype(tp, (TYPE *)NULL));
		    }

		n = ndef(N_FNCALL, tp->Tsubt, 0, n, (NODE*)NULL);

	    /* Hack for returning structures -- see if internal auto
	    ** struct is needed to hold return value, and allocate if so.
	    */
		if (sizetype(n->Ntype) > 2)
		    {
		    static int cntr = 0;
		    char temp[20];
		    if (n->Ntype->Tspec != TS_STRUCT && n->Ntype->Tspec !=TS_UNION)

⌨️ 快捷键说明

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