1File: EXPR.C                                                              Page       1
     1   /*#define DEBUG*/
     2   /*
     3   	Copyright 1982
     4   	Alcyon Corporation
     5   	8716 Production Ave.
     6   	San Diego, Ca.  92121
     7   */
     8    
     9   #include "parser.h"
    10   int opdontop;
    11   int strassign;
    12    
    13   /*
    14    * expr - expression evaluator
    15    *		This handles all the expression syntax in C.  This is a straight-
    16    *		forward operator-stack/oppri scheme for translating infix into
    17    *		a binary expression tree.
    18    */
    19   char *expr()						/* returns 0 or ptr to node*/
    20   {
    21   	register char *p;
    22   	register char *opdsave, *oprsave;
    23   	register int token, op, oppri, i, opdotsave;
    24   	int type, sc;
    25   	long size;
    26    
    27   	opdsave = opdp;
    28   	strassign = 0;
    29   	oprsave = opp;
    30   	opdotsave = opdontop;
    31   	if( !opp || !opdp ) {
    32   		opp = opstack;
    33   		opdp = opdstack;
    34   	}
    35   	else
    36   		opp++;
    37   	opp->o_op = STACKEND;
    38   	opp->o_pri = STKPRI;
    39   	opap = exprp;
    40   	opdontop = 0;
    41    
    42   	while( (token=gettok()) != EOF ) {
    43   		switch( token ) {
    44   	/*
    45   	 * the following are the terminal nodes of the expresion tree,
    46   	 * note that when we see a terminal node, we push it and then go
    47   	 * and get the next token.  When we see an operator, we need to
    48   	 * check the operator stack to see if we can do a reduction.
    49   	 */
    50   		case CINT:
    51   			if( doopd(cnalloc(INT,cvalue)) ) {
    52   exprerr:
    53   				if( token == SEMI || token == RCURBR )
    54   					pbtok(token);
    55   				error("invalid expression");
    56   				opdp = opdsave;
    57   				opp = oprsave;
    58   				opdontop = opdotsave;
    59   				return(0);
1File: EXPR.C                                                              Page       2
    60   			}
    61   			continue;
    62   	
    63   		case CFLOAT:	/*[vlh] 3.4*/
    64   			if( doopd(fpcnalloc(FLOAT,clvalue)) )
    65   				goto exprerr;
    66   			continue;
    67   	
    68   		case CLONG:
    69   			if( doopd(lcnalloc(LONG,clvalue)) )
    70   				goto exprerr;
    71   			continue;
    72   	
    73   		case SYMBOL:
    74   			if( !((p=csp)->s_attrib&SDEFINED) ) {
    75   				if( peek(LPAREN) ) {	/*assume function call*/
    76   					p->s_sc = EXTERNAL;
    77   					p->s_type = FUNCTION|INT;
    78   				}
    79   				else if( commastop )	/*in initialization?*/
    80   					p->s_sc = EXTERNAL;
    81   				else
    82   					error("undefined symbol: %.8s",p->s_symbol);
    83   				p->s_attrib =| SDEFINED;
    84   			}
    85   			if (p->s_sc==EXTERNAL || function(p->t_type)) {
    86   				if (!reducep || p->s_sc==EXTERNAL || peek(LPAREN)) {
    87   					p = enalloc(p);
    88   					p->t_sc = EXTERNAL;
    89   				}
    90   				else {	/* [vlh] 3.4 if (main).... */
    91   					p = cnalloc(CINT,1);	/* eval function name */
    92   				}
    93   			}
    94   			else
    95   				p=snalloc(p->s_type,p->s_sc,p->s_offset,p->s_dp,p->s_ssp);
    96   			if( doopd(p) )
    97   				goto exprerr;
    98   			continue;
    99   	
   100   		case STRING:
   101   			outtstr(cvalue);
   102   			if( doopd(snalloc(ARRAY|CHAR,STATIC,cvalue,0,0)) )
   103   				goto exprerr;
   104   			continue;
   105   	/*
   106   	 * do special checking for unary ops and operators that can be
   107   	 * either unary or binary operators, such as -, &, *, etc.
   108   	 */
   109   		case RESWORD:
   110   			if( cvalue != R_SIZEOF ) {
   111   				goto exprerr;
   112   			}
   113   			token = SIZEOF;
   114   		case COMPL:
   115   		case NOT:
   116   			if( opdontop )			/*can't have: operand unary-op*/
   117   				goto exprerr;
   118   			break;
1File: EXPR.C                                                              Page       3
   119    
   120   		case LBRACK:
   121   			opdontop = 0;
   122   			break;
   123   	
   124   		case RBRACK:
   125   		case RPAREN:
   126   			if( !opdontop )		/*can't be: operator )*/
   127   				goto exprerr;
   128   			break;
   129   	
   130   		case PREINC:
   131   			if( opdontop )			/*assume its lvalue++*/
   132   				token = POSTINC;
   133   			break;
   134    
   135   		case PREDEC:
   136   			if( opdontop )			/*assume its lvalue--*/
   137   				token = POSTDEC;
   138   			break;
   139   	
   140   		case SUB:
   141   			if(!opdontop) {	/*if no operand, assume unary*/
   142   				if( peek(CINT) ) {
   143   					cvalue = -cvalue;
   144   					continue;
   145   				}
   146   				if( peek(CLONG) ) {
   147   					clvalue = -clvalue;
   148   					continue;
   149   				}
   150   				if( peek(CFLOAT) ) {	/*[vlh] 3.4*/
   151   					if (!fflag) {		/* IEEE format */
   152   						if (clvalue & 0x80000000)
   153   							clvalue =& 0x7fffffff;
   154   						else
   155   							clvalue =| 0x80000000;
   156   					}
   157   					else			/* FFP format */
   158   						if (clvalue & 0x80)
   159   							clvalue =& 0xffffff7f;
   160   						else
   161   							clvalue =| 0x80;
   162   					continue;
   163   				}
   164   				token = UMINUS;
   165   			}
   166   			break;
   167   	
   168   		case AND:
   169   			if(!opdontop)
   170   				token = ADDR;
   171   			break;
   172    
   173   		case MULT:
   174   			if( !opdontop )
   175   				token = INDR;
   176   			break;
   177   	/*
1File: EXPR.C                                                              Page       4
   178   	 * for left parenthesis, we need to see if this is a casting operator.
   179   	 */
   180    
   181   		case LPAREN:
   182   			if( !opdontop ) {	/*see if casting or abstract declarator*/
   183   				sc = type = 0;
   184   				if( gettype(&sc,&type,&size) ) {
   185   					sc = (type == STRUCT) ? dalloc(size) : cdp;
   186   					p = snalloc(type,STATIC,0,sc,sc);
   187   					p->t_type =| declarator(1);
   188   					if( !next(RPAREN) )
   189   						goto exprerr;
   190   					if( tdp )
   191   						p->t_type=addtdtype(tdp,p->t_type,p->t_dp,
   192   							&(p->t_ssp));
   193   					pushopd(p);
   194   					token = CAST;
   195   					if( opp->o_op == SIZEOF ) {
   196   						opdontop++;
   197   						continue;
   198   					}
   199   				}
   200   			}
   201   			else  /*we've seen (), look for NACALL*/
   202   				token = (next(RPAREN)) ? MPARENS : CALL;
   203   			break;
   204   	
   205   		case PERIOD:
   206   		case APTR:
   207   			smember++;			/*next token needs to be struct membr*/
   208   			strucptr[smember+instruct] = csp->s_struc;
   209   			break;
   210   	
   211   		}
   212   	/*
   213   	 * we have seen an operator, get its info and then check the operator
   214   	 * stack.
   215   	 */
   216   		if( binop(token) ) {
   217   	/*
   218   	 * handle special binary operators, such as CAST and post-inc and
   219   	 * post-dec.
   220   	 */
   221   			if(!opdontop) {
   222   				if( token != PREDEC && token != PREINC && token != CAST )
   223   					goto exprerr;
   224   			}
   225   			if( token != POSTDEC && token != POSTINC && token != MPARENS )
   226   				opdontop = 0;				/*this fixes x++ op problem.*/
   227   		}
   228   		oppri = oppriority(token);
   229   		if( commastop && token == COMMA )	/*need to stop at comma(init)*/
   230   			oppri = COLPRI;
   231   		if( colonstop && token == COLON )	/*need to stop at colon(case)*/
   232   			oppri = COLPRI;
   233   		while( 1 ) {
   234   			if( oppri > opp->o_pri ||
   235   					(oppri == opp->o_pri && rasop(token)) ) {
   236   	/*
1File: EXPR.C                                                              Page       5
   237   	 * we have encountered a higher priority (or right-associative)
   238   	 * operator, hence we need to stack it.
   239   	 */
   240   				if( ++opp >= &opstack[OPSSIZE] )
   241   					ferror("expression too complex");
   242   				if( token == POSTINC || token == POSTDEC )
   243   					oppri = PSTPRI;
   244   				else if( token == LPAREN || token == LBRACK ||
   245   						token == CALL )
   246   					oppri = CALPRI;
   247   				opp->o_op = token;
   248   				opp->o_pri = oppri;
   249   				break;
   250   			}
   251   	/*
   252   	 * we have encountered a lower priority operator, hence we need to
   253   	 * do a reduction.
   254   	 */
   255   			op = opp->o_op;
   256   			opp--;
   257   			type = CINT;
   258   			switch( op ) {
   259   		
   260   			case STACKEND:			/*we accept the expression...*/
   261   				pbtok(token);
   262   				if (!strassign) {
   263   					if (!maketree(0))
   264   						goto exprerr;
   265   				}
   266   				if (!(p=popopd()))
   267   					goto exprerr;
   268   				opdp = opdsave;
   269   				opp = oprsave;
   270   				opdontop = opdotsave;
   271   				return(p);
   272   		
   273   			case LPAREN:			/*assure these have matching )*/
   274   			case CALL:
   275   				if( token != RPAREN )
   276   					goto exprerr;
   277   				break;
   278    
   279   			case MPARENS:
   280   				if( !maketree(NACALL) )
   281   					goto exprerr;
   282   				continue;
   283   		
   284   			case LBRACK:
   285   				if( token != RBRACK )
   286   					goto exprerr;
   287   				if(!maketree(ADD))	/*array[index]->*(array+index)*/
   288   					goto exprerr;
   289   				op = INDR;
   290   				break;
   291   		
   292   			case PREINC:			/*turn these into binary operators*/
   293   			case POSTINC:			/*which in reality they are...*/
   294   			case PREDEC:
   295   			case POSTDEC:
1File: EXPR.C                                                              Page       6
   296   				pushopd(cnalloc(INT,1));
   297   			default:
   298   				if(!maketree(op))
   299   					goto exprerr;
   300   				continue;			/*see if we can reduce some more...*/
   301   			}
   302   			if( op != LPAREN && !maketree(op) )
   303   				goto exprerr;
   304   			break;
   305   		}
   306   	}
   307   	error("unexpected EOF");
   308   	return(0);
   309   }
   310    
   311   /* talloc - expression area tree node allocation
   312    *		Allocates area and checks for overflow.*/
   313   char *talloc(size)					/* returns pointer to node*/
   314   int size;							/* size of node to alloc*/
   315   {
   316   	register char *p;
   317    
   318   	p = opap;
   319   	if( p + size >= &exprarea[EXPSIZE] )
   320   		ferror("expression too complex");
   321   	opap = p + size;
   322   	return(p);
   323   }
   324    
   325   /*
   326    * enalloc - external name alloc
   327    *		Allocates an expression tree node for an external name and
   328    *		copies symbol table info and symbol into tree node.
   329    */
   330   char *enalloc(sp)					/* returns - none*/
   331   struct symbol *sp;					/* pointer to symbol table entry*/
   332   {
   333   	register struct extnode *ep;
   334    
   335   	ep = talloc(sizeof(*ep));
   336   	ep->t_op = SYMBOL;
   337   	ep->t_sc = sp->s_sc;
   338   	ep->t_type = sp->s_type;
   339   	ep->t_dp = sp->s_dp;
   340   	ep->t_ssp = sp->s_ssp;
   341   	ep->t_offset = sp->s_offset;
   342   	symcopy(sp->s_symbol,ep->t_symbol);
   343   	return(ep);
   344   }
   345    
   346   /* cnalloc - constant node allocation
   347    *		Allocates a constant tree node and fills the info fields.*/
   348   char *cnalloc(type,value)		/* returns pointer to node*/
   349   int type;							/* data type*/
   350   int value;							/* constant value*/
   351   {
   352   	register struct conode *cp;
   353    
   354   	cp = talloc(sizeof(*cp));
1File: EXPR.C                                                              Page       7
   355   	cp->t_op = CINT;
   356   	cp->t_type = type;
   357   	cp->t_dp = 0;
   358   	cp->t_ssp = 0;
   359   	cp->t_value = value;
   360   	return(cp);
   361   }
   362    
   363   /* lcnalloc - long constant node allocation*/
   364   /*		Allocates a constant tree node and fills the info fields.*/
   365   char *lcnalloc(type,value)		/* returns pointer to node*/
   366   int type;						/* data type*/
   367   long value;						/* constant value*/
   368   {
   369   	register struct lconode *cp;
   370    
   371   	cp = talloc(sizeof(*cp));
   372   	cp->t_op = CLONG;
   373   	cp->t_type = type;
   374   	cp->t_dp = 0;
   375   	cp->t_ssp = 0;
   376   	cp->t_lvalue = value;
   377   	return(cp);
   378   }
   379    
   380   /* fpcnalloc - floating point constant node allocation*/
   381   /*		Allocates a constant tree node and fills the info fields.*/
   382   char *fpcnalloc(type,value)		/*[vlh] 3.4 returns pointer to node*/
   383   int type;						/* data type*/
   384   long value;						/* constant value*/
   385   {
   386   	register struct lconode *cp;
   387    
   388   	cp = talloc(sizeof(*cp));
   389   	cp->t_op = CFLOAT;
   390   	cp->t_type = type;
   391   	cp->t_dp = 0;
   392   	cp->t_ssp = 0;
   393   	cp->t_lvalue = value;
   394   	return(cp);
   395   }
   396    
   397   /* tnalloc - tree node allocation*/
   398   /*		Allocates an operator tree node and fills the info fields*/
   399   char *tnalloc(op,type,dp,ssp,left,right)	/* returns pointer to node*/
   400   int op;								/* operator*/
   401   int type;							/* operator type*/
   402   int dp;								/* dimension pointer or other info*/
   403   int ssp;							/* structure length pointer*/
   404   char *left;							/* left subtree*/
   405   char *right;						/* right subtree*/
   406   {
   407   	register struct tnode *tp;
   408    
   409   	tp = talloc(sizeof(*tp));
   410   	tp->t_op = op;
   411   	tp->t_type = type;
   412   	tp->t_dp = dp;
   413   	tp->t_ssp = ssp;
1File: EXPR.C                                                              Page       8
   414   	tp->t_left = left;
   415   	tp->t_right = right;
   416   	return(tp);
   417   }
   418    
   419   /* pushopd - put operand node onto operand stack*/
   420   /*		Checks for operand stack overflow.*/
   421   pushopd(tp)							/* returns - none*/
   422   struct tnode *tp;					/* pointer to tree node to push*/
   423   {
   424   #ifdef DEBUG
   425   	error("pushopd %d",tp->t_op);
   426   #endif
   427   	if( opdp >= &opdstack[OPDSIZE] )
   428   		ferror("expression too complex");
   429   	*opdp++ = tp;
   430   }
   431    
   432   /* popopd - pop operand stack*/
   433   /*		Checks for stack underflow*/
   434   char *popopd()						/* returns ptr to top operand*/
   435   {
   436   	register struct tnode *tp;
   437    
   438   	if( opdp <= &opdstack[0] )
   439   		return(0);
   440   	tp = *--opdp;
   441   #ifdef DEBUG
   442   	error("popopd: %d",tp->t_op);
   443   #endif
   444   	return(tp);
   445   }
   446    
   447   /* doopd - handle constant or symbol node operand*/
   448   /*		Pushes node onto operand stack and handles opdontop flag.*/
   449   doopd(tp)						/* returns 1 if syntax error, 0 for ok*/
   450   struct tnode *tp;				/* pointer to tree node*/
   451   {
   452   	pushopd(tp);
   453   	if( opdontop )
   454   		return(1);
   455   	opdontop++;
   456   	return(0);
   457   }
   458    
   459   	/*
   460   	 * This indicates if a conversion operator is needed given the types
   461   	 * of the two operands.  The upper diagonal is applied ONLY if this
   462   	 * is an assignment operator and the indexes are swapped so the lower
   463   	 * diagonal is used otherwise.
   464   	 * INT		UNSN		LONG		DOUB		PTR
   465   	 */
   466   char cvmap[5][5] {
   467   	0,			UNSN_INT,	LONG_INT,	DOUB_INT,	PTR_INT,	/*INT*/
   468   	INT_UNSN,	0,			LONG_UNSN,	DOUB_UNSN,	PTR_UNSN,	/*UNSN*/
   469   	INT_LONG,	UNSN_LONG,	0,			DOUB_LONG,	PTR_LONG,	/*LONG*/
   470   	INT_DOUB,	UNSN_DOUB,	LONG_DOUB,	0,			BADCONV,	/*DOUB*/
   471   	INT_PTR,	UNSN_PTR,	LONG_PTR,	BADCONV,	PTR_PTR,	/*PTR*/
   472   };
1File: EXPR.C                                                              Page       9
   473    
   474   /*
   475    * maketree - given operator, takes operands and builds up tree
   476    *		This takes the given operator, allocates a node for it
   477    *		and links up the subtrees on the operand stack.  A lot of
   478    *		work is in inserting the proper conversions.
   479    */
   480   maketree(op)						/* returns success or failure */
   481   int op;								/* new root operator*/
   482   {
   483   	register struct tnode *ltp, *rtp, *p;
   484   	register int type, ltype, rtype, lconv, conv, pconv, ilen;
   485    
   486   #ifdef DEBUG
   487   	error("maketree: op = %d",op);
   488   #endif
   489   	if( binop(op) ) {
   490   		if(!(rtp=popopd()))
   491   			return(0);
   492   		rtype = (rtp=funcref(arrayref(rtp)))->t_type;
   493   	}
   494   	if(!(ltp=popopd()))
   495   		return(0);
   496   	if( op == SIZEOF ) {	/* [vlh] 3.4 ilen */
   497   		ilen = dsize(ltp->t_type,ltp->t_dp,ltp->t_ssp);
   498   		pushopd(cnalloc(INT,ilen));
   499   		return(1);
   500   	}
   501   	if( op != ADDR ) {
   502   		ltp = arrayref(ltp);
   503   		if( op != CALL && op != NACALL )
   504   			ltp = funcref(ltp);
   505   	}
   506   	if( specops(op,ltp,rtp) )
   507   		return( 1 );
   508   	ltype = ltp->t_type;
   509   	if( lintegral(op) )
   510   		integral(ltp,LONG);
   511   	if( rintegral(op) )
   512   		integral(rtp,LONG);
   513   	if( lvalop(op) && ltp->t_op != SYMBOL && ltp->t_op != INDR &&
   514   			ltp->t_op != BFIELD )
   515   		error("assignable operand required");
   516   	if( unaryop(op) ) {
   517   		if(!unopeval(op,ltp))
   518   			pushopd(tnalloc(op,ltype,ltp->t_dp,ltp->t_ssp,ltp));
   519   		return;
   520   	}
   521   	if( ltype == STRUCT || rtype == STRUCT ) {
   522   		if (ltype==STRUCT && rtype==STRUCT && op==ASSIGN) { /*[vlh]*/
   523   			pushopd(ltp);
   524   			maketree(ADDR);
   525   			pushopd(rtp);
   526   			maketree(ADDR);
   527   			maketree(STASSIGN);
   528   			strassign = 1;
   529   			return(1);
   530   		}
   531   		ltype = rtype = INT;
1File: EXPR.C                                                              Page      10
   532   		error("illegal structure operation");
   533   	}
   534   	type = ltype;
   535   	if( rtype == TYPELESS ) {
   536   		rtp->t_type = rtype = INT;
   537   		lconv = conv = 0;
   538   	}
   539   	else {
   540   		lconv = ttoconv(ltype);
   541   		conv = ttoconv(rtype);
   542   		if (!asgop(op) && conv > lconv) {
   543   			conv = cvmap[conv][lconv];
   544   			lconv = 1;
   545   			type = rtype;
   546   		}
   547   		else {
   548   			conv = cvmap[lconv][conv];
   549   			lconv = 0;
   550   		}
   551   	}
   552   	if( asgop(op) ) {
   553   		if( (op == ASSIGN || op == FRETURN) && (conv == INT_PTR ||
   554   				conv == UNSN_PTR) && rtp->t_op != CINT )
   555   			error("short assigned to pointer");
   556   		if( op == ASSIGN || op == CAST ) {
   557   			switch( conv ) {
   558    
   559   			case INT_PTR:
   560   			case UNSN_PTR:
   561   			case PTR_PTR:
   562   			case PTR_LONG:
   563   			case LONG_PTR:
   564   				conv = 0;
   565   				break;
   566   			}
   567   		}
   568   	}
   569   	else if( op == COLON && suptype(ltype) != 0 && ltype == rtype )
   570   		conv = 0;
   571   	else if( relop(op) && conv == PTR_PTR )
   572   		conv = 0;
   573   	pconv = 0;
   574   	if ((relop(op) || op==FRETURN) && alltype(ltype) == (STRUCT | POINTER)
   575   				&& (conv == INT_PTR || conv == LONG_PTR))	/* [vlh] 3.4 */
   576   		conv = 0;	/* int compare to struct pointer, no conversion */
   577   	if( conv == PTR_PTR ) {
   578   		conv = 0;
   579   		if( op == SUB ) {
   580   			type = LONG;
   581   			pconv++;
   582   		}
   583   		else if(op != FRETURN && ( (alltype(ltype) != alltype(rtype) ||
   584   					alltype(ltype) != (POINTER|CHAR)) ) )
   585   			conv = BADCONV;
   586   	}
   587   	if( conv ) {
   588   		if( conv == BADCONV )
   589   			error("illegal type conversion");
   590   		else if( lconv ) {
1File: EXPR.C                                                              Page      11
   591   			ltp = cvopgen(ltp,type,conv,psize(rtp),op);
   592   		}
   593   		else {
   594   			rtp = cvopgen(rtp,type,conv,psize(ltp),op);
   595   		}
   596   	}
   597   	else if( op == CAST && rtp->t_type != CHAR ) {
   598   		rtp->t_type = ltp->t_type;
   599   		rtp->t_ssp = ltp->t_ssp;		/* [vlh] 3.4 */
   600   		rtp->t_dp = ltp->t_dp;			/* [vlh] 3.4 */
   601   	}
   602   	if( relop(op) )
   603   		type = INT;
   604   	if( op == CAST )
   605   		pushopd(rtp);
   606   	else if(!binopeval(op,ltp,rtp)) {
   607   		if( btype(ltype) == STRUCT || btype(rtype) != STRUCT )
   608   			p = ltp;
   609   		else
   610   			p = rtp;
   611   		pushopd(tnalloc(op,type,p->t_dp,p->t_ssp,ltp,rtp));
   612   	}
   613   	if( pconv && ltype != (POINTER|CHAR) ) {
   614   		if(!(ltp=popopd()))
   615   			return(0);
   616   		pushopd(cvopgen(ltp,LONG,PTR_LONG,psize(ltp->t_left),op));
   617   	}
   618   	return(1);
   619   }
   620    
   621   /* specops - handle special operators in building tree*/
   622   specops(op,ltp,rtp)				/* returns 1 if op special, 0 otherwise*/
   623   int op;							/* operator*/
   624   struct tnode *ltp;				/* left subtree pointer*/
   625   struct tnode *rtp;				/* right subtree pointer*/
   626   {
   627   	register int type, sr_size, sl_size;
   628    
   629   	type = ltp->t_type;
   630   	switch (op) {
   631    
   632   	case 0:
   633   		break;
   634    
   635   	default:
   636   		return(0);
   637    
   638   	case APTR:							/*expr -> name*/
   639   		integral(ltp,LONG);				/*we need to turn expr into a*/
   640   		ltp->t_type = POINTER|STRUCT;	/*pointer to a struct, then use*/
   641   		pushopd(ltp);					/*expr . name stuff*/
   642   		maketree(INDR);
   643   		ltp = popopd();					/*ltp cannot be 0*/
   644   	case PERIOD:						/*expr . name*/
   645   		if( !(isstel(rtp)) )
   646   			error("invalid structure member name");
   647   		type = rtp->t_type;
   648   		if( array(type) ) {
   649   			type = delspchk(type);
1File: EXPR.C                                                              Page      12
   650   			rtp->t_dp++;
   651   		}
   652   		tadjust(ltp,type,rtp->t_dp,rtp->t_ssp);
   653   		pushopd(ltp);
   654   		maketree(ADDR);
   655   		pushopd(cnalloc(TYPELESS,rtp->t_offset));
   656   		maketree(ADD);
   657   		if( notarray(rtp->t_type) )
   658   			maketree(INDR);
   659   		ltp = popopd();
   660   		if( rtp->t_sc == BFIELDCL )		/*ltp cannot be 0*/
   661   			ltp = tnalloc(BFIELD,type,rtp->t_dp,rtp->t_ssp,ltp);
   662   		break;
   663    
   664   	case QMARK:
   665   		if( rtp->t_op != COLON )
   666   			error("invalid ?: operator syntax");
   667   		if( ltp->t_op == CINT && rtp->t_left->t_op == CINT &&
   668   				rtp->t_right->t_op == CINT )
   669   			ltp->t_value = (ltp->t_value ? rtp->t_left->t_value :
   670   					rtp->t_right->t_value);
   671   		else
   672   			ltp = tnalloc(op,rtp->t_type,0,0,ltp,rtp);
   673   		break;
   674    
   675   	case LAND:
   676   	case LOR:
   677   	case COMMA:							/*don't need conversions here*/
   678   		ltp = tnalloc(op,INT,0,0,ltp,rtp);
   679   		break;
   680    
   681   	case INDR:
   682   		if( ltp->t_op == ADDR  )		/**& is null op*/
   683   			ltp = ltp->t_left;
   684   		else {
   685   			if( function(type) )
   686   				error("indirection on function invalid");
   687   			ltp = tnalloc(INDR,delspchk(type),ltp->t_dp,ltp->t_ssp,ltp);
   688   		}
   689   		break;
   690    
   691   	case STASSIGN:	/*[vlh]*/
   692   		sr_size = psize(rtp);
   693   		sl_size = psize(ltp);
   694   		if( sl_size >= sr_size )
   695   			ltp = tnalloc(STASSIGN,sr_size,0,0,ltp,rtp);
   696   		else
   697   			error("invalid structure assignment");
   698   		break;
   699    
   700   	case NACALL:
   701   	case CALL:
   702   		if( notfunction(type) )
   703   			error("illegal call");
   704   		ltp = tnalloc(op,delspchk(type),ltp->t_dp,ltp->t_ssp,ltp,rtp);
   705   		break;
   706    
   707   	case ADDR:
   708   		if( ltp->t_op == INDR ) {		/*&* is null op*/
1File: EXPR.C                                                              Page      13
   709   /*			ltp->t_left->t_type = addsp(type,POINTER);*/
   710   /*			ltp->t_left->t_dp = ltp->t_dp;*/
   711   /*			ltp->t_left->t_ssp = ltp->t_ssp;*/
   712   			ltp = ltp->t_left;
   713   		}
   714   		else {
   715   			if( ltp->t_op != SYMBOL )
   716   				error("& operand illegal");
   717   			else if( ltp->t_sc == REGISTER )
   718   				error("address of register");
   719   			ltp = tnalloc(ADDR,addsp(type,POINTER),ltp->t_dp,ltp->t_ssp,
   720   					ltp);
   721   		}
   722   		break;
   723   	}
   724   	pushopd(ltp);
   725   	return(1);
   726   }
   727    
   728   /* cvopgen - generate a conversion operator*/
   729   /*		Generates conversions necessary for integers, pointers and longs.*/
   730   char *cvopgen(tp,type,conv,len,op)	/* returns pointer to conv node*/
   731   struct tnode *tp;					/* pointer to node to do conversion*/
   732   int type;							/* type to convert to*/
   733   int conv;							/* specified conversion*/
   734   long len;							/* object length [vlh] 3.4 i=>l */
   735   int op;								/* for cast operator*/
   736   {
   737   	register struct tnode *rtp;
   738   	register int cop, ilen;
   739    
   740   	switch(conv) {
   741    
   742   	case INT_PTR:
   743   	case UNSN_PTR:
   744   		if( op == CAST || op == FRETURN ) {
   745   			cop = INT2L;			/*of the ptd to objects length plus*/
   746   			if( len != 1L ) {		/*an integer to long covnversion*/
   747   				ilen = len;
   748   				rtp = cnalloc(INT,ilen);
   749   				tp = tnalloc(MULT,type,0,0,tp,rtp);
   750   			}
   751   			break;
   752   		}
   753   	case PTR_LONG:						/*need to generate mult or div*/
   754   	case LONG_PTR:						/*of the ptd to objects length*/
   755   		if( len == 1 )
   756   			return(tp);
   757   		ilen = len;
   758   		cop = (conv == PTR_LONG ? DIV : MULT);
   759   		rtp = cnalloc(INT,ilen);
   760   		break;
   761    
   762   	case INT_LONG:
   763   	case UNSN_LONG:
   764   		cop = INT2L;
   765   		break;
   766    
   767   	case INT_DOUB:	/*[vlh] 3.4*/
1File: EXPR.C                                                              Page      14
   768   	case UNSN_DOUB:
   769   		cop = INT2F;
   770   		break;
   771    
   772   	case LONG_DOUB:	/*[vlh] 3.4*/
   773   		cop = LONG2F;
   774   		break;
   775    
   776   	case DOUB_LONG:	/*[vlh] 3.4*/
   777   		cop = FLOAT2L;
   778   		break;
   779    
   780   	case DOUB_INT:	/*[vlh] 3.4*/
   781   	case DOUB_UNSN:
   782   		cop = FLOAT2I;
   783   		break;
   784    
   785   	case LONG_INT:
   786   	case LONG_UNSN:
   787   		cop = LONG2I;
   788   		break;
   789    
   790   	default:
   791   		error("invalid conversion");
   792   		return(tp);
   793   	}
   794   	return( tnalloc(cop,type,0,0,tp,rtp) );
   795   }
   796    
   797   /* tadjust - expression tree type adjustment*/
   798   /*		Adjusts the types of subtrees to agree with the top of the tree.*/
   799   tadjust(tp,type,dp,ssp)				/* returns - none*/
   800   struct tnode *tp;					/* pointer to tree*/
   801   int type;							/* type to adjust to*/
   802   int dp;								/* dimension pointer or info*/
   803   int ssp;							/* structure pointer*/
   804   {
   805   	register int op;
   806    
   807   	tp->t_type = type;
   808   	if( dp >= 0 ) {
   809   		tp->t_dp = dp;
   810   		tp->t_ssp = ssp;
   811   	}
   812   	if( (op=tp->t_op) == ADDR )
   813   		type = delspchk(type);
   814   	else if( op == INDR )
   815   		type = addsp(type,POINTER);
   816   	else if( op != ADD && op != SUB )
   817   		return;
   818   	tadjust(tp->t_left,type,dp,ssp);
   819   }
   820    
   821   /* funcref - handle tree function reference*/
   822   /*		Turns a reference to a function into the address of the function.*/
   823   char *funcref(tp)					/* returns pointer to node*/
   824   struct tnode *tp;					/* pointer to old node*/
   825   {
   826   	if( function(tp->t_type) )
1File: EXPR.C                                                              Page      15
   827   		tp = tnalloc(ADDR,addsp(tp->t_type,POINTER),tp->t_dp,tp->t_ssp,tp);
   828   	return(tp);
   829   }
   830    
   831   /* arrayref - handle tree array reference*/
   832   /*		Turns a reference to an array into the address of the array.*/
   833   char *arrayref(tp)					/* returns pointer to tree node*/
   834   struct tnode *tp;					/* tree node pointer*/
   835   {
   836   	if( array(tp->t_type) && !(isstel(tp)) ) {
   837   		tp->t_dp++;
   838   		pushopd(tp);
   839   		tadjust(tp,delspchk(tp->t_type),-1,0);
   840   		maketree(ADDR);
   841   		tp = popopd();				/*tp cannot be 0*/
   842   	}
   843   	return(tp);
   844   }
   845    
   846   /* integral - checks operand for integral type*/
   847   /*		This checks for needing an integral operand.*/
   848   integral(tp,atype)					/* returns - none*/
   849   struct tnode *tp;					/* pointer to tree node*/
   850   int atype;							/* alternate type allowable*/
   851   {
   852   	register int type;
   853    
   854   	if( (type=tp->t_type) != INT && type != UNSIGNED && type != CHAR &&
   855   			!suptype(type) && type != atype )
   856   		error("invalid operand type");
   857   }
   858    
   859   /* ttoconv - maps normal type into conversion table type*/
   860   ttoconv(type)						/* returns conversion type*/
   861   int type;							/* type to convert*/
   862   {
   863   	switch(type) {
   864    
   865   	case CHAR:
   866   	case INT:
   867   		return(0);
   868    
   869   	case UNSIGNED:
   870   		return(1);
   871    
   872   	case LONG:
   873   		return(2);
   874    
   875   	case FLOAT:
   876   	case DOUBLE:
   877   		return(3);
   878    
   879   	default:
   880   		return(4);
   881   	}
   882   }
   883    
   884   /* binopeval - does binary operator constant expression evaluation*/
   885   /*		Does the constant expression evaluation for binary operators.*/
1File: EXPR.C                                                              Page      16
   886   binopeval(op,ltp,rtp)				/* returns 1 if done, 0 if not*/
   887   int op;								/* operator to evaluate*/
   888   struct tnode *ltp;					/* pointer to left subtree*/
   889   struct tnode *rtp;					/* pointer to right subtree*/
   890   {
   891   	register int lvalue, rvalue;
   892    
   893   	if( ltp->t_op != CINT )
   894   		return(0);
   895   	lvalue = ltp->t_value;
   896   	if( rtp->t_op != CINT )
   897   		return(0);
   898   	rvalue = rtp->t_value;
   899   	switch (op) {
   900    
   901   	case ADD:
   902   		lvalue =+ rvalue;
   903   		break;
   904    
   905   	case SUB:
   906   		lvalue =- rvalue;
   907   		break;
   908    
   909   	case MULT:
   910   		lvalue =* rvalue;
   911   		break;
   912    
   913   	case DIV:
   914   		lvalue =/ rvalue;
   915   		break;
   916    
   917   	case MOD:
   918   		lvalue =% rvalue;
   919   		break;
   920    
   921   	case AND:
   922   		lvalue =& rvalue;
   923   		break;
   924    
   925   	case OR:
   926   		lvalue =| rvalue;
   927   		break;
   928    
   929   	case XOR:
   930   		lvalue =^ rvalue;
   931   		break;
   932    
   933   	case LSH:
   934   		lvalue =<< rvalue;
   935   		break;
   936    
   937   	case RSH:
   938   		lvalue =>> rvalue;
   939   		break;
   940    
   941   	case EQUALS:
   942   		lvalue = (lvalue == rvalue);
   943   		break;
   944    
1File: EXPR.C                                                              Page      17
   945   	case NEQUALS:
   946   		lvalue = (lvalue != rvalue);
   947   		break;
   948    
   949   	case GREAT:
   950   		lvalue = (lvalue > rvalue);
   951   		break;
   952    
   953   	case LESS:
   954   		lvalue = (lvalue < rvalue);
   955   		break;
   956    
   957   	case GREATEQ:
   958   		lvalue = (lvalue >= rvalue);
   959   		break;
   960    
   961   	case LESSEQ:
   962   		lvalue = (lvalue <= rvalue);
   963   		break;
   964    
   965   	default:
   966   		return(0);
   967   	}
   968   	ltp->t_value = lvalue;
   969   	pushopd(ltp);
   970   	return(1);
   971   }
   972    
   973   /* unopeval - unary operator constant expression evaluation*/
   974   /*		Does constant expression evaluation for unary operators.*/
   975   unopeval(op,tp)						/* returns 1 if done, 0 otherwise*/
   976   int op;								/* operator to evaluate*/
   977   struct tnode *tp;					/* pointer to subexpression*/
   978   {
   979   	register int value;
   980    
   981   	if( tp->t_op != CINT )
   982   		return(0);
   983   	value = tp->t_value;
   984   	switch( op ) {
   985    
   986   	case COMPL:
   987   		value = ~ value;
   988   		break;
   989    
   990   	case UMINUS:
   991   		value = - value;
   992   		break;
   993    
   994   	case NOT:
   995   		value = ! value;
   996   		break;
   997    
   998   	default:
   999   		return(0);
  1000   	}
  1001   	tp->t_value = value;
  1002   	pushopd(tp);
  1003   	return(1);
1File: EXPR.C                                                              Page      18
  1004   }
  1005    
  1006   /* cexpr - evaluate a constant integer expression*/
  1007   /*		Used in evaluating array bounds, bit field numbers, etc.*/
  1008   cexpr()
  1009   {
  1010   	register struct tnode *tp;
  1011   	register char *savep;
  1012    
  1013   	savep = exprp;
  1014   	exprp = opap;
  1015   	commastop++;
  1016   	if( (tp=expr()) && tp->t_op != CINT )
  1017   		error("constant required");
  1018   	commastop--;
  1019   	exprp = savep;
  1020   	return( tp->t_value );
  1021   }
  1022    
  1023   /* delspchk - delete one special reference and check if non-zero*/
  1024   delspchk(type)						/*returns new special type*/
  1025   int type;							/* type to modify*/
  1026   {
  1027   	if(!(suptype(type)))
  1028   		error("bad indirection");
  1029   	return( delsp(type) );
  1030   }
  1031    
  1032   /* psize - return size of object ptd at by pointer*/
  1033   long								/* [vlh] 3.4 int => long */
  1034   psize(tp)							/* returns size of object in bytes*/
  1035   struct tnode *tp;					/* pointer to tree node*/
  1036   {
  1037   	if ( !(suptype(tp->t_type)) )	/* what case ??? */
  1038   		return(1);
  1039   	return( dsize(delsp(tp->t_type),tp->t_dp,tp->t_ssp) );
  1040   }
