1File: EXPR.C                                                              Page       1
     1   /*
     2   	Copyright 1981
     3   	Alcyon Corporation
     4   	8716 Production Ave.
     5   	San Diego, Ca.  92121
     6   */
     7    
     8   /* Expression evaluator */
     9    
    10   # include "as68.h"
    11    
    12   /*precedence of operators*/
    13   # define PAO	2		/*AND, OR*/
    14   # define PPM	2		/*+ -*/
    15   # define PMD	3		/** /*/
    16   # define PLP	1		/* (*/
    17   # define PRP	4		/* )*/
    18   # define PEE	0		/* all other special chars*/
    19    
    20    
    21   /*global integers for this package*/
    22   struct it	exitm;		/*expression item*/
    23   int	prcnt;		/*paren count*/
    24   int	rval;		/*relocation value*/
    25   int lpflg;
    26   int lastopr;	/*last token was operator when set*/
    27    
    28   long gval();	/*get operand value*/
    29    
    30   /*
    31    * expression evaluator
    32    *	call with:
    33    *		address of function to get input
    34    *	returns:
    35    *		item type in itype
    36    *		item value in ival
    37    *		relocation flag in reloc:
    38    *			0 => absolute
    39    *			1 => data
    40    *			2 => text
    41    *			3 => bss
    42    *			4 => external
    43    *
    44    * The only expressions involving externals which are legal are
    45    *		external+constant or external-constant
    46    */
    47    
    48   struct it *piop, *pitr;
    49   int iop, itr;
    50    
    51   struct it opstk[OPSTLEN];	/*operator stack*/
    52   struct it tree[TREELEN];		/*operand stack*/
    53    
    54   expr(iploc)
    55   int (*iploc)();
    56   {
    57   	register int i, ipr;
    58    
    59   	extflg = starmul = iop = lpflg = 0;
1File: EXPR.C                                                              Page       2
    60   	piop = &opstk[0];
    61   	itr = -1;		/*tree stack pointer*/
    62   	pitr = &tree[0];
    63   	pitr--;
    64   /* form end of expression operator*/
    65   	opstk[0].itty = ITSP;	/*special character*/
    66   	opstk[0].itop.wd2 = '?';
    67   	lastopr = 1;
    68    
    69   /* get an input item*/
    70   	while(1) {
    71   		if(itr >= TREELEN-2) {
    72   			rpterr("expr tree overflow\n");
    73   			abort();
    74   		}
    75   		if(iop >= OPSTLEN-1) {
    76   			rpterr("expr opstk overflow\n");
    77   			abort();
    78   		}
    79   		(*iploc)();		/*get an input term*/
    80   		if (itype==ITPC) return;
    81   		starmul=0;		/* * is location counter*/
    82    
    83   /* special character*/
    84   		if(itype==ITSP) {
    85   			ipr = gprc(i=ival.wd2);	/*get precedence of character*/
    86   			if(ipr==PEE)			/*end of expression*/
    87   				break;
    88   			lastopr = 1;
    89   			if(ipr==PLP) {		/*left paren*/
    90   				lpflg++;
    91   				prcnt++;
    92   				iop++;			/*up stack pointer*/
    93   				piop++;
    94   				piop->swd1=exitm.swd1;	/*put operator on stack*/
    95   				piop->itop=exitm.itop;
    96   				continue;
    97   			}
    98   			if(ipr==PRP) {		/*right paren*/
    99   				if(lpflg) { exerr(1); return; }
   100   				starmul = 1;	/* * is multiply*/
   101   				prcnt--;		/*down one level*/
   102    
   103   				while (piop->itop != '(') {	/* top stk is '(' */
   104   					itr++;			/*up tree pointer*/
   105   					pitr++;
   106   					pitr->swd1 = piop->swd1;	/*move operator*/
   107   					pitr->itop = piop->itop;
   108   					iop--;			/*reduce operand stack*/
   109   					piop--;
   110   				}
   111   				iop--;		/*remove stack*/
   112   				piop--;
   113   				continue;
   114   			}
   115    
   116   			while(ipr<=gprc(i=piop->itop.wd2)) { /* >= precedence */
   117   				itr++;
   118   				pitr++;
1File: EXPR.C                                                              Page       3
   119   				pitr->swd1 = piop->swd1;	/*move operator*/
   120   				pitr->itop = piop->itop;
   121   				iop--;			/*reduce operand stack*/
   122   				piop--;
   123   			}
   124   			iop++;			/*up operator stack*/
   125   			piop++;
   126   			piop->swd1 = exitm.swd1;	/*put in operator stack*/
   127   			piop->itop = exitm.itop;
   128   			continue;
   129   		}
   130    
   131   /* symbol or constant*/
   132   		else {
   133   			lastopr = lpflg = 0;		/*clear flag*/
   134   			itr++;		/*up tree pointer*/
   135   			pitr++;
   136   			pitr->swd1 = exitm.swd1;	/*put in tree*/
   137   			pitr->itop = exitm.itop;
   138   			starmul = 1;		/* * is multiply*/
   139   			continue;
   140   		}
   141   	}	/* end while(1)... */
   142    
   143   /*output the rest of the operator stack to the tree*/
   144   	for(i=iop; i>=0; i--) {
   145   		itr++;
   146   		pitr++;
   147   		pitr->swd1 = piop->swd1;	/*move operator*/
   148   		pitr->itop = piop->itop;
   149   		piop--;
   150   	}
   151    
   152   	collapse();
   153   }
   154    
   155   /* collapse the tree into one entry*/
   156   collapse()
   157   {
   158   	register int rv1, rv2, topr, i, bos;
   159   	register long tv1, tv2;
   160    
   161   	bos = 0;
   162   exct1:
   163   	if(itr>=3) {
   164   		piop = &tree[bos];
   165   		iop = bos;
   166   		while (iop<=(itr-3+bos) && (piop->itty==ITSP ||
   167   				(piop+1)->itty==ITSP || (piop+2)->itty!=ITSP)) {
   168   			iop++;
   169   			piop++;
   170   		}
   171   		if (iop<=(itr-3+bos)) {
   172   			tv1 = gval(piop);		/*get value of first operand*/
   173   			rv1 = rval;				/*relocation value*/
   174   			tv2 = gval(piop+1);
   175   			rv2 = rval;
   176   			topr = (piop+2)->itop;	/*operator*/
   177   	
1File: EXPR.C                                                              Page       4
   178   	/* handle operators */
   179   			if (topr == '+') {
   180   				tv1=+ tv2;
   181   				rv1 = ckrl1(rv1,rv2);	/*relocation*/
   182   			}
   183   			else if (topr == '-') {
   184   				tv1 =- tv2;
   185   				rv1 = ckrl2(rv1,rv2);	/*relocation*/
   186   			}
   187   			else {
   188   				switch(topr) {	/*operator*/
   189   					case '/':	/* division */
   190   						tv1 =/ tv2; break;
   191   					case '*':	/* multiplication */
   192   						tv1 =* tv2; break;
   193   					case '&':	/* logical and */
   194   						tv1 =& tv2; break;
   195   					case '!':	/* logical or */
   196   						tv1 =| tv2; break;
   197   					case '<':	/* left shift */
   198   						tv1 =<< tv2.wd2; break;
   199   					case '>':	/* right shift */
   200   						tv1 =>> tv2.wd2; break;
   201   					default:	/*invalid operator*/
   202   						exerr(2); return;
   203   				}
   204   				rv1 = ckrl3(rv1,rv2);	/* relocation */
   205   			}
   206   	
   207   	/*put new value in tree*/
   208   			if (iop==bos) {
   209   				bos =+ 2;
   210   				iop = bos;
   211   			}
   212   			piop = &tree[iop];
   213   			piop->itty = ITCN;		/*must be constant*/
   214   			piop->itop = tv1;		/*value*/
   215   			piop->itrl = rv1;		/*relocation value*/
   216   	
   217   			if (iop != bos) {	/* push up the rest of the tree... */
   218   				i = iop + 2 - bos;
   219   				pitr = piop+2;
   220   				for(; i<itr; i++) {
   221   					piop++;
   222   					pitr++;
   223   					piop->swd1 = pitr->swd1;
   224   					piop->itop = pitr->itop;
   225   				}
   226   			}
   227   			itr =- 2;
   228   			goto exct1;
   229   		}
   230   	}
   231    
   232   /* check for unary minus and unary plus*/
   233   	if (tree[bos+1].itty!=ITSP && tree[bos].itop.wd2=='?')
   234   		{ exerr(3); return; }
   235   	if (tree[bos+1].itty!=ITSP || tree[bos].itty==ITSP) {
   236   		reloc = ABS;
1File: EXPR.C                                                              Page       5
   237   		ival = 0;
   238   		itype = ITCN;
   239   		return;
   240   	}
   241    
   242   	if(tree[bos+1].itop.wd2!='?') {		/*end of statement*/
   243   		if(tree[bos+1].itop.wd2!='+') {	/*ignore unary plus*/
   244   			if(tree[bos+1].itop.wd2!='-') {	/* invalid operator */
   245   				exerr(4);
   246   				return;
   247   			}
   248   			tree[bos+1].itop = -gval(&tree[bos]);
   249   			tree[bos+1].itty = ITCN;
   250   			tree[bos+1].itrl = tree[bos].itrl;
   251   			bos++;
   252   			itr--;
   253   			goto exct1;
   254   		}
   255   	}
   256   /* send results back to caller*/
   257   	if ((itype = tree[bos].itty)==ITCN)
   258   		ival = gval(&tree[bos]);
   259   	else {
   260   		ival = tree[bos].itop;
   261   		if(itype==ITSY && !(ival.ptrw2->flags&SYDF)) {	/*undef symbol*/
   262   			reloc = ABS;
   263   			ival = 0;
   264   			itype = ITCN;
   265   			return;
   266   		}
   267   	}
   268   	get_val(tree[bos].itrl);
   269   }
   270    
   271   /*
   272    *if defined symbol get value and say constant
   273    * except for externals and equated registers
   274    */
   275   get_val(reloc_val)
   276   int reloc_val;
   277   {
   278   	if(itype==ITSY && (ival.ptrw2->flags&(SYXR|SYER))==0) {
   279   		if(ival.ptrw2->flags&SYRA)	/*get symbol relocation factor*/
   280   			reloc = DATA;
   281   		else if(ival.ptrw2->flags&SYRO)
   282   			reloc = TEXT;
   283   		else if(ival.ptrw2->flags&SYBS)
   284   			reloc = BSS;
   285   		else reloc = ABS;
   286   		ival = ival.ptrw2->vl1;		/*symbol vaue*/
   287   		itype = ITCN;				/*constant*/
   288   	}
   289   	else
   290   		if(itype == ITSY && ival.ptrw2->flags&SYXR) {	/*external symbol*/
   291   			fixext(ival.ptrw2);
   292   			reloc = EXTRN;
   293   		}
   294   		else
   295   			reloc = reloc_val;		/*relocation value of item*/
1File: EXPR.C                                                              Page       6
   296   }
   297    
   298   exerr(n)	/* [vlh] */
   299   int n;
   300   {
   301   	uerr(6);
   302   	ival = 0;
   303   	itype = ITCN;
   304   	reloc = ABS;
   305   }
   306    
   307   /*
   308    * get precedence of a operator
   309    *	call with
   310    *		operator
   311    *	returns
   312    *		precedence
   313    */
   314   gprc(dprc)
   315   {
   316    
   317   	switch(dprc) {
   318    
   319   		case '+':
   320   		case '-':
   321   		case '&':		/* and*/
   322   		case '!':		/* or*/
   323   		case '^':		/*exclusive or*/
   324   			return(PPM);
   325    
   326   		case '/':
   327   		case '*':
   328   		case '<':		/*left shift*/
   329   		case '>':		/*right shift*/
   330   			return(PMD);
   331    
   332   		case '(':
   333   			if(lastopr)
   334   				return(PLP);
   335   			break;
   336    
   337   		case ')':
   338   			if(!prcnt)	/*no left parens*/
   339   				break;
   340   			return(PRP);
   341    
   342   	}
   343   	return(PEE);	/*end of expression*/
   344   }
   345    
   346   /*
   347    * get value from an it format item
   348    *	call with
   349    *		address of it format item
   350    *	returns
   351    *		the value
   352    *		relocation value in rval
   353    *	calls uerr if it cant get a value
   354    */
1File: EXPR.C                                                              Page       7
   355   long gval(avwrd)
   356   struct it *avwrd;
   357   {
   358   	register struct it *vwrd;
   359   	register struct symtab *p;
   360    
   361   	vwrd = avwrd;
   362   	if(vwrd->itty == ITCN) {	/*constant*/
   363   		rval = vwrd->itrl;
   364   		return(vwrd->itop);			/*value*/
   365   	}
   366   	if(vwrd->itty != ITSY) {
   367   		uerr(6);
   368   		rval = ABS;
   369   		return(0);
   370   	}
   371   	p = vwrd->itop.ptrw2;
   372   	if(p->flags&SYXR) {		/*external reference*/
   373   		fixext(p);
   374   		return(0);
   375   	}
   376   	if((p->flags&SYDF) != SYDF || (p->flags&SYER)) {
   377   		uerr(6);
   378   		rval = ABS;
   379   		return(0);
   380   	}
   381   	rval = (p->flags&SYRA) ? DATA : (p->flags&SYRO) 	/* reloc of item */
   382   				? TEXT : (p->flags&SYBS) ? BSS : ABS;
   383   	return(p->vl1);
   384   }
   385    
   386   /*
   387    * get items for expression evaluator (pass one)
   388    *	returns:
   389    *		item type in itype
   390    *		item value in ival
   391    *		item in it format in exitm
   392    */
   393   p1gi()
   394   {
   395   	if(fcflg)		/*used item so must pass it*/
   396   		gterm(TRUE);
   397   	if(!fcflg && ckspc(fchr)==1) {
   398   		fcflg=1;	/*just pass first character*/
   399   		itype=ITSP;	/*special char*/
   400   		ival=fchr;	/*value is the char*/
   401   	}
   402   	else {	/*get a whole term*/
   403   		fcflg = 0;
   404   		gterm(TRUE);		/*get a term*/
   405   		if(itype==ITSY) {	/* got a symbol*/
   406   			ival.ptrw2=lemt(sirt,FALSE);	/*look it up in main table*/
   407   			if(ival.ptrw2==lmte)	/*not there before*/
   408   				mmte();		/*put it in table*/
   409   		}
   410   		else
   411   			if(itype == ITCN)
   412   				exitm.itrl = reloc;
   413   	}
1File: EXPR.C                                                              Page       8
   414   	exitm.itty = itype;
   415   	exitm.itop = ival;
   416   }
   417    
   418   /*
   419    * get items for expression evaluator (pass 2)
   420    * returns:
   421    *		item type in itype
   422    *		item value in ival
   423    *		item in it format in exitm
   424    */
   425   p2gi()
   426   {
   427   	if(pitw==pnite) {	/*end of statement*/
   428   		itype = ITSP;
   429   		ival = ' ';		/*blank*/
   430   		exitm.itty = itype;
   431   		exitm.itop = ival;
   432   		return;
   433   	}
   434    
   435   	if((itype = pitw->itty) == ITPC) {	/*vlh*/
   436   		pitw->itop = loctr;
   437   		if (p2flg || format==6) itype = pitw->itty = ITCN;
   438   	}
   439   	ival  = pitw->itop;	/*value*/
   440   	exitm.swd1 = pitw->swd1;
   441   	exitm.itop = ival;
   442   	pitw++;
   443   }
   444    
   445   /*
   446    *check for a special character
   447    *	call with
   448    *		character to check
   449    *	returns:
   450    *		0 => character is number or letter
   451    */
   452   ckspc(acksc)
   453   {
   454   	register cksc;
   455    
   456   	cksc = acksc;
   457   	if (isalnum(cksc)) return(0);
   458   	return((index("_~*.@$%\'",cksc) != -1) ? 0 : 1);	/*[vlh] compacted*/
   459   }
   460    
   461   /* generate new relocation for op + op*/
   462   ckrl1(rv1,rv2)
   463   {
   464   	if(rv1==rv2)
   465   		return(rv1);
   466   	if(rv1==ABS || rv2==ABS)
   467   		return(rv1+rv2);	/*the one that is not ABS*/
   468   	uerr(27);
   469   	return(ABS);
   470   }
   471    
   472   /*generate new relocation for op - op*/
1File: EXPR.C                                                              Page       9
   473   ckrl2(rv1,rv2)
   474   {
   475   	if(rv2==EXTRN)
   476   		uerr(26);
   477   	if(rv1==rv2)
   478   		return(ABS);
   479   	if(rv2==ABS)
   480   		return(rv1+rv2);
   481   	uerr(27);
   482   	return(ABS);
   483   }
   484    
   485   /*generate new relocation for op /*&|<>^! op*/
   486   ckrl3(rv1,rv2)
   487   {
   488   	if(rv1!=ABS || rv2!=ABS)
   489   		uerr(27);
   490   	return(ABS);
   491   }
   492    
   493   fixext(p)
   494   struct symtab *p;
   495   {
   496   	if(extflg)
   497   		uerr(36);		/*two externals in expr*/
   498   	extflg++;
   499   	extref = p->vl1.wd2;	/*get external #*/
   500   	rval = EXTRN;
   501   	itype = ITCN;
   502   	ival = 0;
   503   }
   504    
   505    
